Давайте создадим две модели SQLAlchemy:
class Child(Base):
__tablename__ = "child"
id = Column(String, primary_key=True)
parent_id = Column(String, ForeignKey("parent.id"), nullable=False)
class Parent(Base):
__tablename__ = "parent"
id = Column(String, primary_key=True)
children = relationship("Child", lazy="joined")
То, чего я пытаюсь добиться, - это наличие логического атрибута (назовем его has_deps
) для Parent
, который будет True
, когда есть дети для данного родителя.
У меня также есть некоторые ограничения:
- Он должен быть доступен при преобразовании объекта в dict
- Он не должен генерировать коррелированный подзапрос
Я пробовал разные методы:
- Использование
column_property
с exists
дало мне коррелированный подзапрос
Parent.has_deps = column_property(
exists([Child.parent_id]).where(Child.parent_id == Parent.id)
)
результаты в:
SELECT parent.id AS parent_id, EXISTS (SELECT child.parent_id FROM child WHERE child.parent_id = parent.id) AS anon_1, parent.id AS id_1, child_1.id AS child_1_id, child_1.parent_id AS child_1_parent_id
FROM parent LEFT OUTER JOIN child AS child_1 ON parent.id = child_1.parent_id
- Использование
hybrid_property
не загружается во время запроса и не доступно с помощью dict и не имеет для этого цели
@has_deps.expression
def has_deps(cls):
return case([(Child.parent_id != None, True)], else_=False)
(не будет даже быть привязанным к левому внешнему соединению псевдонимов, сгенерированному отношением)
Например, это запрос, который я хочу, чтобы ORM выполнил, просто выполнив session.query(Parent).all()
:
SELECT parent.id AS parent_id, CASE WHEN child_1.parent_id IS NOT NULL THEN true ELSE false END AS has_deps, parent.id AS id_1, child_1.id AS child_1_id, child_1.parent_id AS child_1_parent_id
FROM parent LEFT OUTER JOIN child AS child_1 ON parent.id = child_1.parent_id