在SQLAlchemy中查询属性列表而不是元组

Pap*_*K24 19 python sqlalchemy

我正在查询模型的ID,并获取(int,)元组列表而不是id列表.有没有办法直接查询属性?

result = session.query(MyModel.id).all()
Run Code Online (Sandbox Code Playgroud)

我意识到这是可能的

results = [r for (r,) in results]
Run Code Online (Sandbox Code Playgroud)

查询是否可以直接返回该表单,而不必自己处理它?

Mar*_*ers 22

传入ORM检测的描述符(如列)时,每个结果都是一个命名元组,即使只有一列也是如此.您可以使用列表解析中的列名来"展平"列表(您可以删除.all()调用,迭代也会检索对象):

result = [r.id for r in session.query(MyModel.id)]
Run Code Online (Sandbox Code Playgroud)

或者在循环for循环并将其解压缩到目标的单元素元组时使用它是元组的事实:

result = session.query(MyModel.id)
for id, in result:
    # do something with the id
Run Code Online (Sandbox Code Playgroud)

后者也可用于列表理解:

[id for id, in session.query(MyModel.id)]
Run Code Online (Sandbox Code Playgroud)

您实际上没有任何选项可以强制行结果只是单个id值.

  • BTW` [id for id,在session.query(MyModel.id)]`也可以工作 - >没有all()调用.根据SQLAlchemy文档,最好像这样迭代.这就像它变得非常好:).谢谢这非常有帮助. (2认同)

Kim*_*Kim 9

Result.scalars()可以创建一个ScalarResult来接收单个对象而不是 Rows。使用核心风格的查询语法,您的示例可能如下所示:

>>> from sqlalchemy import select
>>> from sqlalchemy.orm import sessionmaker

>>> session = sessionmaker(...)
>>> result = session.execute(select(MyModel.id))
>>> result.scalars().all()
[1, 2, 3, ...]
Run Code Online (Sandbox Code Playgroud)

注意:如果选择多列,.scalars().all()则仅返回第一列。因此select(MyModel.id, MyModel.something)具有与 相同的 ScalarResult select(MyModel.id)。但是,要使用 选择所有列select(MyModel),ScalarResult 再次很有帮助,因为它返回对象列表MyModel


ana*_*thi 7

奇怪的是 SQLalchemy 没有提供适当的解决方案。在 sqlalchemy 中,如果选择一个成员变量(例如列),则每个结果都是一个命名元组,如@Martijn 所说。我使用python的zip函数找到了解决方案

邮编方式

邮编官方文档

zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)] 返回元组列表,其中每个元组包含 i-每个参数序列中的第 th 个元素。返回的列表在长度上被截断为最短参数序列的长度。

来到你的例子

result = session.query(MyModel.id).all()
result = zip(*result)[0]
Run Code Online (Sandbox Code Playgroud)

输出:

[id1, id2, id3...]
Run Code Online (Sandbox Code Playgroud)

它是如何工作的,如果你传递这样的列表,它将展平作为参数给出的元组列表

[(key11, key21), (key12,key22)]
Run Code Online (Sandbox Code Playgroud)

Zip 会将这个元组列表转换为

[(key11, key12), (key21, key22)]
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您需要 MyModel 的 tupe 的每个初始值,以便您可以从列表中获取第 0 个元组。

链法

from itertools import chain
result = session.query(MyModel.id).all()  # result [(id1,), (id2,), (id3,)]
result = list(chain(*result))
Run Code Online (Sandbox Code Playgroud)

输出

[id1, id2, id3]
Run Code Online (Sandbox Code Playgroud)

For 循环

result = session.query(MyModel.id).all()  # result [(id1,), (id2,), (id3,)]
result = [id for id, in result]
Run Code Online (Sandbox Code Playgroud)

输出

[id1, id2, id3]
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常常见的用例,它让我感到困惑,为什么 SQLAlchemy 没有使这变得更容易。 (7认同)