SQLAlchemy, эквивалентный методу annotate () Джанго - PullRequest
4 голосов
/ 29 октября 2010

Я делаю соединение в 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 Ответ

6 голосов
/ 30 октября 2010

На самом деле, "items.first (). Count" будет работать, так как возвращаемый вами кортеж является именованным кортежем ... но, думаю, вы не хотите видеть items.first (). Item.foo.

Второй способ, которым вы могли бы сделать это, - просто запустить результат вашего запроса () через функцию, которая создает желаемый результат:

def process(q):
    for item, count in q:
        item.count = count
        yield count

edit: Вот обобщенная версия:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...