- changed status to wontfix
Relationship lazy configuration doesn't work with polymorphism
Issue #2762
resolved
Testcase:
from sqlalchemy import create_engine, Column, ForeignKey, Integer
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class RelatedModel(Base):
__tablename__ = 'related_model'
id = Column(Integer, primary_key=True)
class Model(Base):
__tablename__ = 'model'
id = Column(Integer, primary_key=True)
mtype = Column(Integer, nullable=False)
__mapper_args__ = {'polymorphic_on': mtype}
class SubModel(Model):
__tablename__ = 'submodel'
id = Column(Integer, ForeignKey('model.id'), primary_key=True)
__mapper_args__ = {'polymorphic_identity': 1}
related_model_id = Column(Integer, ForeignKey('related_model.id'))
related_model = relationship('RelatedModel', lazy='joined')
def main():
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
s = SubModel()
s.related_model = RelatedModel()
session.add(s)
session.commit()
session.close()
session = Session()
s = session.query(Model).one()
session.close()
s.related_model
I expect that the relationship SubModel -> RelatedModel
is already loaded, even when querying against the base class. However, the above code raises DetachedInstanceError: Parent instance <SubModel at 0x2b465f0> is not bound to a Session; lazy load operation of attribute 'related_model' cannot proceed
.
Comments (2)
-
repo owner -
reporter If you load the polymorphic collection already as relationship via
query.options(joinedload('model'))
, I guess only the last option works? - Log in to comment
a polymorphic load on joined table inheritance by default only loads from the base table, not any of the related tables, until attributes specific to the subclass are accessed (as is the case with
related_model
here). therefore a joined eager load from SubModel->related_model is ignored here.The solution here is to use
with_polymorphic
, of which there are three ways to specify (mapper level,query.with_polymorphic()
, and the newerwith_polymorphic()
standalone function), specifying that loads forModel
should also join out to load submodels of typeSubModel
: