при условии, что эти модели:
class A(Base):
...
targets = relationship("B", back_populates='a')
...
class B(Base):
...
a_id = Column(Integer, ForeignKey('a.id'))
a = relationship("A", back_populates='targets')
attr = Column(ENUM('a', 'b', 'c', name='options'), default='a')
...
Как я могу написать hybrid_attribute.expression
для возврата True для всех A
s, где любые связанные B
s имеют значение атрибута attr
в ('b', 'c')
? (Это также должно вернуть False, если нет связанных B
s.)
Это приводит меня на полпути:
# hybrid_attribute expression in A model
@example_attr.expression
def example_attr(cls):
return case(
[
(
B.attr.in_(('b','c')),
True
)
],
else_=False
)
Но тогда как мне сгруппировать их по A.id
, если, если любые связанные B
s равны True
, тогда значение столбца example_attr
для этой строки A
равно True
?
Я хочу, чтобы top мог делать: session.query(A).filter(A.example_attr.is_(True)).all()
РЕДАКТИРОВАТЬ 1:
Кажется, этот SQL дает желаемый результат:
select a.id, coalesce(bool_or(a_id_b_attr.status), false)
from a left outer join (
select b.a_id as a_id, b.attr in ('b', 'c') as status from b
) as a_id_b_attr
on a.id = a_id_b_attr.a_id group by a.id;
Но у меня небольшая проблема со ссылками на псевдонимы полей в подзапросе:
sub = db.session.query(B.a_id.label('a_id'), B.attr.in_(('b', 'c')).label('status')).subquery()
db.session.query(
A.id,
db.func.coalesce(
db.func.bool_or(sub.status),
False
)
).\
outerjoin(sub, A.id == sub.key_id).\
group_by(A.id)
Который выбрасывает AttribubteError
, поскольку sub
не имеет псевдонимов.