Как запросить базу данных по идентификатору с помощью SqlAlchemy?


95

Мне нужно запросить базу данных SQLAlchemy idчем-то похожим на

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

но для id. Как мне это сделать? [Поиск в Google и SO не помог]


Пожалуйста, предоставьте более подробную информацию, например, эквивалентный SQL или псевдокод, делающий то, что вы хотите. Что такое «идентификатор базы данных SQLAlchemy»?
Daniel Kluev

Есть ли в вашей таблице столбец идентификаторов?
Кейт

Ответы:


130

В запросе есть функция получения, которая поддерживает запросы по первичному ключу таблицы, как я предполагаю id.

Например, чтобы запросить объект с ID 23:

User.query.get(23)

Примечание. Как уже упоминалось несколькими другими комментаторами и ответами, это не просто сокращение для «Выполнить фильтрацию запроса по первичному ключу». В зависимости от состояния сеанса SQLAlchemy запуск этого кода может запросить базу данных и вернуть новый экземпляр, или он может вернуть экземпляр объекта, запрошенного ранее в вашем коде, без фактического запроса базы данных. Если вы еще этого не сделали, подумайте о прочтении документации по сеансу SQLAlchemy, чтобы понять последствия.


8
Get функция также поддерживает несколько первичных ключей: YourModel.query.get((pk1, pk2)). Обратите внимание на кортеж.
marc_aragones 01

3
В get()функции запросов объектов по первичному ключу. Если вы хотите запросить id, вы должны idсначала установить в качестве первичного ключа.

46

Вы можете запросить пользователя с id = 1 следующим образом

session.query(User).get(1)


7

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
Чем такое неожиданное поведение?
Соломон Учко

Я имею в виду, что если вы находитесь в транзакции (еще не сеансе.commit), get()кажется, что вы получите объект результата в памяти (без фактического запроса базы данных), но filter().first()всегда будет запрашивать базу данных.
panda912

Возможно ли одновременное изменение базы данных во время транзакции? Если нет, то getлучше использовать за счет увеличения эффективности.
Соломон Учко

1
поскольку я знаю, что sqlalchemy не может работать с асинхронным материалом (кажется, только с gevent), и да, getэто более эффективно.
panda912

Почему .first () отличается от .get () в том, что касается транзакции? Всегда ли .first () возвращается в базу данных? Это то, что .get () сначала просматривает текущий env, чтобы узнать, знает ли он этот идентификатор или что-то в этом роде?
msouth

1

Если вы используете tables reflection вас могут возникнуть проблемы с приведенными решениями. (Предыдущие решения здесь не работали для меня).

В итоге я использовал:

session.query(object._class_).get(id)

( objectбыл получен путем отражения из базы данных, поэтому вам нужно использовать.__class__ )

Надеюсь, это поможет.


0

Во-первых, вы должны установить 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)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.