SQLAlchemy: выбор столбцов объекта в запросе

Можно ли контролировать, какие столбцы запрашиваются в методе запроса SQLAlchemy, при этом все еще возвращающие экземпляры объекта, который вы запрашиваете (хотя и частично заполнены)?

Или необходимо, чтобы SQLAlchemy выполняла SELECT * для сопоставления с объектом?

(Я знаю, что запрос отдельных столбцов доступен, но он не отображает результат для объекта, а только для компонента именованного кортежа).

Например, если объект User имеет атрибуты userid, name, password и bio, но вы хотите, чтобы запрос заполнял только userid и имя для возвращаемых объектов:

# hypothetical syntax, of course:
for u in session.query(User.columns[userid, name]).all():
    print u

будет печатать:

<User(1, 'bob', None, None)> 
<User(2, 'joe', None, None)>
...

Это возможно; если да, то как?

Ответ 1

вы можете запрашивать отдельные столбцы, которые возвращают именованные кортежи, которые на самом деле действуют так же, как ваш сопоставленный объект, если вы просто передаете шаблон или что-то еще:

http://www.sqlalchemy.org/docs/orm/tutorial.html#querying

или вы можете установить различные столбцы в отображаемом классе как "отложенные", либо конфигурационно, либо используя параметры:

http://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#deferred-column-loading

там есть старый билет в trac для чего-то, называемого "defer_everything_but()", если кому-то захотелось предоставить тесты, и поэтому нет причин, которые не могли бы быть добавлены функцией, здесь быстрая версия:

from sqlalchemy.orm import class_mapper, defer
def defer_everything_but(entity, cols):
    m = class_mapper(entity)
    return [defer(k) for k in 
            set(p.key for p 
                in m.iterate_properties 
                if hasattr(p, 'columns')).difference(cols)]

s = Session()
print s.query(A).options(*defer_everything_but(A, ["q", "p"]))

defer() должен действительно принимать множественные числа, добавленный билет # 2250 для этого (отредактируйте: как отмечено в комментарии, это в 0,9 как load_only())

Ответ 2

Простым решением для меня было:

users = session.query(User.userid, User.name)
for user in users:
    print user

будет печатать:

<User(1, 'bob')> 
<User(2, 'joe')>
...