On Aug 3, 2010, at 3:37 AM, Enrico wrote:
> I'm trying to use the object association pattern from the doco. Is it
> the case that this requires departure from Declarative mode and is it
> wrong to mix with non-declarative?
it is perfectly fine to mix non-declarative with declarative. However, it is
almost always not necessary to use non_primary=True. non_primary is when you
want to have an alternative SELECT statement for a particular entity, and you
need that SELECT wrapped in a mapping so that it can be used in a
relationship().
> I looked at the example code
> optimized_al.py but it didn't seem to be exactly what I want. I want a
> symmetric relation for adjacency of nodes in an undirected graph with
> cycles. ie. it is not a tree.
The key to using association object is that you are no longer using the
"secondary" attribute of relationship() (and hence no secondaryjoin).
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import *
from sqlalchemy.orm import sessionmaker, relationship
Base = declarative_base()
class Node(Base):
__tablename__ = 'node'
id = Column(Integer, primary_key=True)
class Adj(Base):
__tablename__ = 'adj'
node_id = Column(Integer(), ForeignKey('node.id'),
primary_key=True)
adj_node_id = Column(Integer(), ForeignKey('node.id'),
primary_key=True)
node = relationship(Node, primaryjoin=node_id==Node.id,
backref='adj_node')
adj_node = relationship(Node,
primaryjoin=adj_node_id==Node.id,
backref='node')
def __str__(self):
return "Adj(node=%s, adj_node=%s)" % (self.node_id, self.adj_node_id)
engine = create_engine('sqlite://', echo=True)
Base.metadata.create_all(engine)
sess = sessionmaker(engine)()
n1, n2, n3 = Node(), Node(),Node()
n1.node.append(Adj(node=n2))
n1.node.append(Adj(node=n3))
sess.add_all([
n1, n2, n3
])
sess.commit()
print sess.query(Adj).all()
> <code>
> class Node(DeclarativeBase):
> __tablename__ = 'node'
> #with some columns id etc.
>
> adj = Table(u'adj', metadata,
> Column(u'node', Integer(), ForeignKey('node.id'),
> primary_key=True),
> Column(u'adj_node', Integer(), ForeignKey('node.id'),
> primary_key=True),
> Column(u'somedata_id', Integer(), ForeignKey('somedata.id')),
> )
> class Adj(object):
> __table__ = _adj
> #relation definitions
> node = relation('node') # self-referential, bidirectional, many-
> to-many
> somedata = relation('SomeData')
>
> def __init__(self, n1, n2):
> self.n1 = n1
> self.n2 = n2
>
> mapper(Adj, adj, properties={
> 'node': relation(Adj,
> primaryjoin = Node.id==Adj.node,
> #secondaryjoin = Node.id==Adj.adj_node?,
> backref=backref('adj_node',
> remoteside=[_adj.c.node])
> )
> }, non_primary=True)
> </code>
>
> I put the non_primary and the primaryjoin in after error messages told
> me to but now this is causing another error 'Adj' has not attribute
> 'node' I even tried primaryjoin = Node.id==adj.c.node but then I got
> "Could not locate any equated, locally mapped column pairs." This
> seems to be getting a bit more complicated than it should be already.
> Is there an example of an association object in Declarative style?
> Also, is it possible to do it with forward references only?
>
> --
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/sqlalchemy?hl=en.
>
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.