如何使用SqlAlchemy按id查询数据库?

133

我需要通过 SQLAlchemy 数据库的 id 进行查询,类似于:

User.query.filter_by(username='peter')

但是针对id,我该怎么做呢?[在Google和SO上搜索都没有帮助]


请提供更多细节,例如执行您想要的操作的等效SQL或伪代码。"SQLAlchemy数据库ID"是什么? - Daniel Kluev
你的表格是否有一个 id 列? - Keith
6个回答

187

查询有一个获取函数,支持按表的主键进行查询,我假设它是id

例如,要查询ID为23的对象:

User.query.get(23)

注意:正如其他评论者和答案所提到的那样,这不仅仅是“对主键执行查询过滤”的简写。根据SQLAlchemy会话的状态,运行此代码可能会查询数据库并返回一个新实例,也可能会返回先前在您的代码中查询的对象实例而不实际查询数据库。如果您尚未这样做,请考虑阅读SQLAlchemy会话文档以了解影响。

12
Get函数也支持多个主键:YourModel.query.get((pk1, pk2))。注意这是一个元组。 - marc_aragones
3
get()函数通过主键查询对象。如果您想通过“id”查询,您应该首先将“id”设置为主键。 - user10875014
5
自1.4版本起,Query.get()已被弃用,它的替代方法是session.get(User, 5)吗? - jave.web
@MarceloGazzola 请在新线程中提出新问题,如果您需要评论旧线程,请仅对单个答案进行评论,而不是三个不同的答案。谢谢。话虽如此,User.query.filter(User.id.in_((23,24,25,58,21))).all()应该可以满足您的需求。 - ggorlen
抱歉,我在阅读SQLAlchemy文档时遇到了困难。这个被弃用的Query.get()方法和此问题中列出的User.query.get(23)方法有什么不同?https://docs.sqlalchemy.org/en/14/orm/query.html#sqlalchemy.orm.Query.get 我想避免使用被弃用的方法,但我还没有弄清楚是否应该使用User.query.get(23)。谢谢您的时间。 - Zhao Li

67

要查询id为1的用户,您可以使用以下代码:

session.query(User).get(1)


11

get() 有时候并不如你所期望。如果你的交易已经完成:

>>> session.query(User).get(1)
[SQL]: BEGIN (implicit)
[SQL]: SELECT user.id AS user_id, user.name AS user_name, user.fullname AS user_fullname
FROM user
WHERE user.id = ?
[SQL]: (1,)
<User(u'ed', u'Ed Jones')>

如果您正在进行交易,get()将在不查询数据库的情况下将结果对象存储在内存中:

>>> session.query(User).get(1)
<User(u'ed', u'Ed Jones')>

最好使用这个:

>>> session.query(User.name).filter(User.id == 1).first()
[SQL]: SELECT user.name AS user_name
FROM user
WHERE user.id = ?
 LIMIT ? OFFSET ?
[SQL]: (1, 1, 0)
(u'Edwardo',)

1
这种行为为何是意外的? - Solomon Ucko
我的意思是,如果你在一个事务中(但还没有session.commit),get()似乎会在内存中给你结果对象(而不实际查询数据库),但filter().first()总是会查询数据库。 - panda912
在事务期间并发更改数据库是否可能?如果不行,使用get更好,因为它可以提高效率。 - Solomon Ucko
1
据我所知,SQLAlchemy 无法处理异步操作(似乎只能与 gevent 一起使用),而且是的,get 更有效率。 - panda912
1
这是一个很好的观点,但我认为这并不意外 - 这正是每个带有缓存的ORM的工作方式...如果它不这样做,那才是出乎意料的。 - George Mauer
显示剩余2条评论

3
如果您使用表反射,可能会遇到解决方案无效的问题。(此前的解决方案对我无效)。
我最终使用的是:
session.query(object.__class__).get(id)

(object是通过反射机制从数据库中检索出来的,这就是为什么你需要使用.__class__)

希望这可以帮到你。


2

从SQLAlchemy 2.0开始,您可以使用:

with Session(engine) as session:
    user = session.get(User, 1)
    if user is not None:
        print(f'# user: {user.username}')
        print(user)

1

首先,您应该将id设置为主键。
然后,您可以使用query.get()方法通过已经是主键的id来查询对象。

由于query.get()方法是通过主键来查询对象的。
Flask-SQLAlchemy文档中推断出。

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy()
db.init_app(app)

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)

def test():
    id = 1
    user = User.query.get(id)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接