我在 SQLAlchemy 中做这样的连接:
items = Item.query\
.outerjoin((ItemInfo, ItemInfo.item_id==Item.id))
items.add_columns(ItemInfo.count)
这会导致 SQLAlchemy 返回元组:
>>> items.first()
(<Item ...>, 2)
如果将“计数”值作为项目的属性返回,我会更喜欢它,即我想这样做:
>>> items.first().count
2
这是否受支持?
最佳答案
实际上,“items.first().count”会起作用,因为您返回的元组是一个命名元组……但我猜您不想看到 items.first().item.foo。
您可以执行此操作的第二种方法是通过构造您想要的结果类型的函数来运行 query() 的结果:
def process(q):
for item, count in q:
item.count = count
yield count
编辑:这是一个通用版本:
from sqlalchemy.orm.query import Query
class AnnotateQuery(Query):
_annotations = ()
def annotate(self, key, expr):
q = self.add_column(expr)
q._annotations = self._annotations + (key, )
return q
def __iter__(self):
if not self._annotations:
return super(AnnotateQuery, self).__iter__()
else:
for row in super(AnnotateQuery, self):
item, remaining = row[0], row[1:]
for i, key in enumerate(self._annotations):
setattr(item, key, remaining[i])
yield item
# session usage:
Session = sessionmaker(query_cls=AnnotateQuery)
# query usage:
q = Session.query(Item).outerjoin(...).annotate('count', Item.count)
第三,您更改 Item 类以支持此功能。您将使用 column_property()
将选择子查询应用于您的类:http://www.sqlalchemy.org/docs/orm/mapper_config.html#sql-expressions-as-mapped-attributes .如果你希望属性的加载是有条件的,你可以使用 deferred: http://www.sqlalchemy.org/docs/orm/mapper_config.html#deferred-column-loading .
关于python - SQLAlchemy 等同于 Django 的 annotate() 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4052724/