Say that I have two SQLAlchemy models that look like...
class Child(ModelBase):
__tablename__ = "child"
parent_id = sa.Column(sa.Integer, sa.ForeignKey("parent.id"))
parent = orm.relationship(
"Parent",
backref=orm.backref("children", lazy="raise_on_sql"),
lazy="joined",
)
class Parent(ModelBase):
__tablename__ = "parent"
id = sa.Column(sa.Integer, primary_key=True)
is_default = sa.Column(sa.Boolean)
... and I have a query to select parents and their children like...
parents = session.query(Parent)
.options(joinedload(Parent.children))
.all()
If the query returns no parent records where is_default = True
then I want to (1) create a new parent instance with is_default=True
, and (2) add it to the parents
list to be returned, like...
if not [p for p in parents if p.is_default]:
parent = Parent(is_default=True)
parents.add(parent)
session.add(parent)
session.flush() # necessary to get id of new record
return [{"parent": p, "children": p.children} for p in parents]
This works if a new record isn't created, but because parent
wasn't loaded via the query, if a new record is created then the above raises...
sqlalchemy.exc.InvalidRequestError: 'Parent.children' is not available due to lazy='raise_on_sql'
I have a rough understanding of the session's identity map, and I know that I can issue another query with the new parent's id
to select 0 rows and populate the map, but how can I mark the relationship as loaded for a new record without having to issue another query, especially one that is 100% useless as it's guaranteed that there aren't any children for the new parent?
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…