我有4张桌子:
class Cebola(Base):
__tablename__ = 'cebolas'
id = Column(Integer, primary_key=True, autoincrement=True)
class Checklist(Base):
__tablename__ = 'checklists'
id = Column(Integer, primary_key=True, autoincrement=True)
checklist_type = Column(String)
cebola_id = Column(Integer, ForeignKey('cebolas.id'))
cebola = relationship('Cebola', backref=backref('checklists'))
__mapper_args__ = {'polymorphic_on': checklist_type,
'polymorphic_identity': 'generic'}
class ChecklistA(Checklist):
__tablename__ = 'checklist_a'
id = Column(Integer, ForeignKey('checklists.id', ondelete='CASCADE'), primary_key=True)
notes = Column(Unicode)
__mapper_args__ = {'polymorphic_identity': 'a'}
class ChecklistB(Checklist):
__tablename__ = 'checklist_b'
id = Column(Integer, ForeignKey('checklists.id', ondelete='CASCADE'), primary_key=True)
notes = Column(Unicode)
__mapper_args__ = {'polymorphic_identity': 'b'}
现在我需要一种方法(可能是混合属性),它会告诉我在Cebola中有多少个notes <> ''
的清单。
我已添加:
class Cebola(Base):
@hybrid_property
def number_of_comments(self):
return len([c for c in self.checklists if c.notes])
@number_of_comments(cls)
def number_of_comments(cls):
???
我在SQLAlchemy - Writing a hybrid method for child count中发现了类似的问题,但我的例子有点复杂。
答案 0 :(得分:1)
下面应该开始:
class Cebola(Base):
__tablename__ = 'cebolas'
id = Column(Integer, primary_key=True, autoincrement=True)
@hybrid_property
def number_of_comments(self):
# return len([c for c in self.checklists if c.notes])
# @NOTE:1: below will prevent error for those that do not have `notes` column
# @NOTE:2: in any case this may issue a lot of SQL statements to load all subclasses of checklists relationship, so is not really efficient
return len([c for c in self.checklists
if hasattr(c, 'notes') and c.notes])
@number_of_comments.expression
def number_of_comments(cls):
from sqlalchemy import select
ce, cl, cla, clb = [
_.__table__ for _ in (Cebola, Checklist, ChecklistA, ChecklistB)]
s = (
select([func.count(cl.c.id).label("number_of_comments")])
.select_from(cl.outerjoin(cla).outerjoin(clb))
.where(or_(cla.c.notes != None, clb.c.notes != None))
.where(cl.c.cebola_id == cls.id)
.correlate(cls)
.as_scalar()
)
return s
查询中的用法:
q = session.query(Cebola, Cebola.number_of_comments)
for cebola, number_of_comments in q.all():
print(cebola, number_of_comments)