SQLAlchemy:在查询中选择对象的哪些列

32 投票
3 回答
69082 浏览
提问于 2025-04-16 23:06

可以控制在SQLAlchemy的查询方法中查询哪些列吗,同时还能返回你查询的对象实例(虽然是部分填充的)?

还是说SQLAlchemy必须执行一个 SELECT * 来映射到一个对象上?

我知道可以查询单独的列,但这样得到的结果并不会映射到一个对象上,而只是映射到一个命名元组的某个部分。

举个例子,如果User对象有userid、name、password和bio这些属性,但你只想让查询返回userid和name这两个属性的对象:

# 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)>
...

这样做可能吗?如果可以的话,怎么做?

3 个回答

9

关于 load_only 的最新文档在这里

http://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#load-only-cols

如果你想在模型定义的时候控制这个,可以使用 deferred

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

28

对我来说,一个简单的解决办法是:

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

这段代码会输出:

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

你可以查询单独的列,这样会返回一些命名元组,这些元组实际上和你映射的对象很像,特别是当你把它们传给模板或者其他地方使用的时候:

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() 提供)

撰写回答