SQLAlchemy等同于Django的annotate()方法

时间:2010-10-29 14:22:55

标签: python django orm sqlalchemy

我在SQLAlchemy中正在进行这样的连接:

 items = Item.query\
    .outerjoin((ItemInfo, ItemInfo.item_id==Item.id))
 items.add_columns(ItemInfo.count)

这会导致SQLAlchemy返回元组:

 >>> items.first()
 (<Item ...>, 2)

如果“count”值将作为项目的属性返回,我更喜欢它,即我想这样做:

 >>> items.first().count
 2

支持吗?

1 个答案:

答案 0 :(得分:6)

实际上,“items.first()。count”会起作用,因为你得到的元组是一个命名的元组......但是猜测你不想看到items.first()。item.foo。< / p>

你可以做到这一点的第二种方法就是通过一个构造你想要的结果的函数来运行你的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