【问题标题】:SQLAlchemy: selecting which columns of an object in a querySQLAlchemy:选择查询中对象的哪些列
【发布时间】:2011-10-22 02:27:44
【问题描述】:

是否可以控制在 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)>
...

这可能吗?如果有,怎么做?

【问题讨论】:

    标签: python orm sqlalchemy


    【解决方案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()

    【讨论】:

    • 在sa>=0.9.0,见load_only()
    • 对于 load_only() 我可能很傻,但是有没有办法将 orm 列的列表传递给它?现在,如果我只显式地传递一个 ormmodel.col1,load_only() 就会接受它,并且生活很美好。但是,如果我改为传递列实体列表 [ormmodel.col1, ormmodel.col2] 它会在 strategy_options.py 中的 _bind_loader() 中的第 779 行“映射器选项需要”“字符串键或属性列表”。我是否需要了解如何通过列表?还是调用 load_only 时需要显式定义每一列?
    【解决方案2】:

    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

    【讨论】:

      【解决方案3】:

      一个对我有用的简单解决方案是:

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

      将打印:

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

      【讨论】:

      • 在您的代码中,user 不是User 实例(问题是关于什么的)。这是一个命名元组。实际上,它只会打印(1, 'bob')\n(2, 'joe')
      • 没有任何奇怪的循环。最佳答案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 2019-05-07
      • 2022-01-25
      相关资源
      最近更新 更多