Ah, so, it turns out to be more subtle than I first thought. It took me quite a while to narrow it down to an easily reproducible case. To trigger the behavior you need to be: joinedloading() along a backref, and also I think it matters that I am joining back onto the same table and returning a bunch of objects. Quite a corner case I think.
This code demonstrates the behavior - it issues a second query in the for loop for the 'A' which has no child. from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class A(Base): __tablename__ = 'a' id = Column(Integer, primary_key=True) join_table = Table('parent_child', Base.metadata, Column('id_a', ForeignKey('a.id')), Column('id_b', ForeignKey('a.id'))) parent = relationship("A", secondary=join_table, primaryjoin = (id == join_table.c.id_a), secondaryjoin = (id == join_table.c.id_b), uselist=False, backref=backref("child", uselist=False)) e = create_engine("sqlite://", echo=True) Base.metadata.create_all(e) sess = Session(e) a1 = A() a2 = A(parent=a1) sess.add(a1) sess.add(a2) sess.commit() sess.close() results = sess.query(A).options(joinedload("child")).all() print "----" for a in results: print a.child is None On Mon, Mar 24, 2014 at 8:34 PM, Michael Bayer <mike...@zzzcomputing.com>wrote: > > On Mar 24, 2014, at 2:09 PM, Philip Scott <safetyfirstp...@gmail.com> > wrote: > > > > > Is this a bug, or perhaps some expected side effect of the joined load? > > seemed like something that might be possible but the scalar loader is > initializing the attribute to None to start with, here's a simple test that > doesn't show your behavior, so see if you can just modify this one to show > what you are seeing. note we only need to see that 'bs' is in a1.__dict__ > to prevent a lazyload. > > from sqlalchemy import * > from sqlalchemy.orm import * > from sqlalchemy.ext.declarative import declarative_base > > Base = declarative_base() > > class A(Base): > __tablename__ = 'a' > > id = Column(Integer, primary_key=True) > bs = relationship("B", secondary=Table('atob', Base.metadata, > Column('aid', ForeignKey('a.id')), > Column('bid', ForeignKey('b.id')) > ), > uselist=False) > > class B(Base): > __tablename__ = 'b' > > id = Column(Integer, primary_key=True) > > e = create_engine("sqlite://", echo=True) > Base.metadata.create_all(e) > > sess = Session(e) > sess.add(A()) > sess.commit() > sess.close() > > a1 = sess.query(A).options(joinedload("bs")).first() > assert 'bs' in a1.__dict__ > assert a1.__dict__['bs'] is None > assert a1.bs is None > > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at http://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.