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 sqlalch...@googlegroups.com. > To unsubscribe from this group, send email to > sqlalchemy+unsubscr...@googlegroups.com. > 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 sqlalch...@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.