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.

Reply via email to