查询数据库时,我只想加载指定的列。使用 with_entities
创建查询需要引用模型列属性,而使用 load_only
创建查询需要一个与列名对应的字符串。我更喜欢使用 load_only
,因为使用字符串创建动态查询更容易。这两者之间有什么区别?
查询数据库时,我只想加载指定的列。使用 with_entities
创建查询需要引用模型列属性,而使用 load_only
创建查询需要一个与列名对应的字符串。我更喜欢使用 load_only
,因为使用字符串创建动态查询更容易。这两者之间有什么区别?
有几个区别。当丢弃不需要的列时(如问题所示),最重要的区别是使用 load_only
仍会创建一个对象(即一个 Model 实例),而使用 with_entities
只会得到所选列的值的元组。
>>> query = User.query
>>> query.options(load_only('email', 'id')).all()
[<User 1 using e-mail: n@d.com>, <User 2 using e-mail: n@d.org>]
>>> query.with_entities(User.email, User.id).all()
[('n@d.org', 1), ('n@d.com', 2)]
load_only()
可以推迟从模型中加载特定的列。它会从查询中删除这些列。你仍然可以稍后访问所有其他列,但是只有在访问它们时才会执行额外的查询(在后台)。
"仅加载" 在您将用户图片之类的内容存储在数据库中,但不希望在不需要它们时浪费传输时间时非常有用。例如,在显示用户列表时,可能只需要使用这个功能:
User.query.options(load_only('name', 'fullname'))
with_entities()
可以添加或删除(简单来说:替换)模型或列;您甚至可以使用它来修改查询,使用自己的函数(例如 func.count()
)替换所选实体:
query = User.query
count_query = query.with_entities(func.count(User.id)))
count = count_query.scalar()
请注意,生成的查询结果与 query.count()
不同,后者可能比较慢 - 至少在 MySQL 中(因为它会生成一个子查询)。
with_entities 的另一个额外功能的例子是:query = (
Page.query
.filter(<a lot of page filters>)
.join(Author).filter(<some author filters>)
)
pages = query.all()
# ok, I got the pages. Wait, what? I want the authors too!
# how to do it without generating the query again?
pages_and_authors = query.with_entities(Page, Author).all()