On Wednesday, March 23, 2011 1:40:30 AM UTC+1, Michael Bayer wrote: > > > On Mar 22, 2011, at 6:03 PM, Debilski wrote: > > > Hi, > > I’m having a problem with the collection append method in a many-to- > > many relationship with association object. Basically, I’d like to > > connect classes of type Entity through a Context object (which holds a > > description of the connection type). Programmatically, it should go > > like > > > > experiment = Entity() > > observer = Entity() > > experiment.connect("has Observer", observer) > > print experiment.connected # prints [observer] > > > > However, what happens is that this code results in observer being > > printed twice unless some other operation occurred before that > > statement. It is not really clear to me why this happens. The code is > > as follows: > > so when you append to a list, if multiple appends of the same object (same > identity) occur, you'll see those duplicated elements in the list as it is > in memory. Once the session is committed, the attribute is expired - on a > load back, relational rules mean you can only get the element from a > one-to-many back once, so then you see it once. > > The element is duplicated because of this: > > context = Context(back_referenced=self, > connected=connection_object, connection_type=connection_type) > self.connections.append(context) > > Context(back_referenced=self) triggers an event based on the backref in the > "backreferenced" relationship that also appends the item to the "connected" > list. The "connected.append" afterwards does the same thing a second time. > "Context.back_referenced" and "Entity.connections" are two sides of the > same relational coin, and establishment via relationship/backref establishes > this behavior in memory pre-flush as well. >
Thank you! Of course, when I specify the back_referenced manually, there is no need to use append. Seems pretty clear. Cheers /rike > > > > from sqlalchemy import Column, ForeignKey, String, Integer, > > create_engine > > from sqlalchemy.orm import relationship, backref, scoped_session, > > sessionmaker > > from sqlalchemy.ext.declarative import declarative_base > > Base = declarative_base() > > > > class Entity(Base): > > __tablename__ = "entities" > > id = Column('id', Integer, primary_key=True) > > > > def connect(self, connection_type, connection_object): > > """Connect this entity with connection_object via the > > connection_type.""" > > context = Context(back_referenced=self, > > connected=connection_object, connection_type=connection_type) > > self.connections.append(context) > > > > @property > > def connected(self): > > return [c.connected for c in self.connections] > > > > > > class Context(Base): > > __tablename__ = "contexts" > > entity_id = Column('entity_id', Integer, > > ForeignKey(Entity.id), primary_key=True) > > connected_id = Column('connected_id', Integer, > > ForeignKey(Entity.id), primary_key=True) > > > > connection_type = Column('connection_type', String(500)) > > > > # Each entity can have a context of related entities > > back_referenced = relationship(Entity, > > backref=backref('connections', cascade="all"), > > primaryjoin=entity_id==Entity.id) > > > > connected = relationship(Entity, > > backref=backref('back_references', cascade="all"), > > primaryjoin=connected_id==Entity.id) > > > > def __repr__(self): > > return "Context(entity_id={id!s}, connected_id={cid!s}, > > connection_type={type})".format(id=self.entity_id, > > cid=self.connected_id, type=self.connection_type) > > > > def __str__(self): > > return "Context({e} has {t} > > {c})".format(e=self.back_referenced, t=self.connection_type, > > c=self.connected) > > > > session = scoped_session(sessionmaker(autocommit=True)) > > engine = create_engine("sqlite://") > > session(bind=engine) > > Base.metadata.create_all(engine) > > > > e1 = Entity() > > e2 = Entity() > > > > session.add(e1) > > session.add(e2) > > > > e1.connect("C", e2) > > > > print e1.connected > > print "Number of connections to e1", len(e1.connected) > > > > # prints: > > # [<__main__.Entity object at 0x101613dd0>, <__main__.Entity object at > > 0x101613dd0>] > > # Number of connections to e1 2 > > > > Is there anything I can do to get the correct number of entities back? > > > > Thanks > > /rike > > > > -- > > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > > To post to this group, send email to sqlal...@googlegroups.com. > > To unsubscribe from this group, send email to > sqlalchemy+...@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 sqlalchemy@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.