在SQLAlchemy中,为什么我的load_only不过滤我指定的任何列?

发布于 2021-01-29 14:56:33

基本上,我已经在正常的完整查询中创建了一个数据库,这是我使用的代码以及生成的响应。

db.session.query(User).all()

生成的查询如下:

<User(email='howard@howard.com', fullname='Howard', company='howard', address='None', password='howard')>,  <User(email='emailhoward', fullname='None', company='None', address='None', password='passwordhoward')>

这是合乎逻辑的,因为我正在从表中提取所有内容。但是,当我尝试使用load_only专门选择一列时,在这种情况下为email列。我使用的代码是:

db.session.query(User).options(load_only(User.address)).all()
db.session.query(User).options(load_only('email')).all()

这两个命令给我相同的结果:

<User(email='howard@howard.com', fullname='Howard', company='howard', address='None', password='howard')>,<User(email='emailhoward', fullname='None', company='None', address='None', password='passwordhoward')>

这非常奇怪,因为我应该在查询中仅获得一列。但是,当我使用此:

db.session.query(User.email).select_from(User).filter_by(email=email).first()[0]

它神奇地为我返回了仅一列。我需要使用load_only,因为我有要重用相同功能的动态表,而不是维护许多功能集。谁能告诉我load_only命令是什么问题,或者我做错了什么?

谢谢。

关注者
0
被浏览
110
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    没问题,只是有点误会。

    <User(email='howard@howard.com', fullname='Howard', company='howard', address='None', password='howard')>
    

    是模型对象的字符串表示形式User它是在User.__repr__()访问延迟列时提取延迟列的方法。

    使用load_only()您定义一组列,以在最初为一个实体加载的同时延迟所有其他列。但是推迟一列并不意味着它某种程度上就无法使用或包含一些“无价值”标记(实际上,它实际上是在幕后)。当第一次引用每个延迟属性时,SQLAlchemy将发出SELECT以便获取其值。从日志中应该显而易见:

    In [7]: u = session.query(User).options(load_only(User.email)).first()
    2018-05-14 16:04:49,218 INFO sqlalchemy.engine.base.Engine SELECT user.id AS user_id, user.email AS user_email 
    FROM user
     LIMIT ? OFFSET ?
    2018-05-14 16:04:49,218 INFO sqlalchemy.engine.base.Engine (1, 0)
    
    In [8]: u.fullname
    2018-05-14 16:04:53,773 INFO sqlalchemy.engine.base.Engine SELECT user.fullname AS user_fullname 
    FROM user 
    WHERE user.id = ?
    2018-05-14 16:04:53,773 INFO sqlalchemy.engine.base.Engine (2,)
    Out[8]: 'Bar'
    

    您可以使用检查API检查列是否已推迟。InstanceState.unloaded保存没有加载值的键集。使用它,您可以将您的内容修改User.__repr__为:

    class User(Base):
        ...
    
        def __repr__(self):
            state = inspect(self)
            def ga(attr):
                return (repr(getattr(self, attr))
                        if attr not in state.unloaded
                        else "<deferred>")
    
            attrs = " ".join([f"{attr.key}={ga(attr.key)}"
                              for attr in state.attrs])
            return f"<User {attrs}>"
    

    或者,您可以遍历 display,
    如果尚未加载值,则InstanceState.attrs显示AttributeState.loaded_value为符号
    NO_VALUE

    class User(Base):
        ...
    
        def __repr__(self):
            state = inspect(self)    
            attrs = " ".join([f"{attr.key}={attr.loaded_value!r}"
                              for attr in state.attrs])
            return f"<User {attrs}>"
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看