Reputation: 7276
I want to load an entity via a sqlalchemy query while explicitly avoiding loading a specific class of entity as a field on any instance of any child of my loaded entity. Take the below data model:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.orm import relationship
base = declarative_base()
class Parent(base):
__tablename__ = 'Parent'
uid = Column(Integer, primary_key=True)
class Child(base):
__tablename__ = 'Child'
uid = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('Parent.uid'))
parent = relationship('Parent', backref="children")
class OtherChild(base):
__tablename__ = 'OtherChild'
uid = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('Parent.uid'))
parent = relationship('Parent', backref="other_children")
class Bicycle(base):
__tablename__ = 'Bicycle'
uid = Column(Integer, primary_key=True)
child_id = Column(Integer, ForeignKey('Child.uid'))
child = relationship('Child', backref="bicycles")
child_id = Column(Integer, ForeignKey('OtherChild.uid'))
child = relationship('OtherChild', backref="bicycles")
If I do a Parent.query.all()
then I'm going to get back any Child
or OtherChild
objects which are in those Parent
objects in the children
and other_children
fields, respectively. Further, I'll get any Bicycle
objects which are embedded inside either the Child
or OtherChild
objects.
I wish to do a query
on Parent
which explicitly avoids loading any Bicycle
objects on any children regardless how deep they may be in the data structure.
Update:
It is possible to constrain the children returned in a query using options(contains_eager(<pathtoclass>))
. For example (not tested but pretty sure it would work):
query = query.outerjoin(Child, primaryjoin.expression).\
options(contains_eager('children'))
However, this requires explicitly describing the options
for each path. In a circumstance with hundreds of valid options this becomes onerous. I would prefer to just express something like query.contains_eager(CLASS)
.
Upvotes: 2
Views: 482
Reputation: 139
According to the docs, relationships use lazy loading by default. No Bicycle
objects will load until you directly access the relationship attribute.
Since the relationships appear to be unidirectional from Bicycle
to Child
and from Bicycle
to OtherChild
, you shouldn't have to worry about loading Bicycle
objects unless you specifically query for them.
Upvotes: 1