Bagaimana cara query database dengan id menggunakan SqlAlchemy?


96

Saya perlu menanyakan database SQLAlchemy dengan idsesuatu yang mirip dengan

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

tapi untuk id. Bagaimana saya melakukan ini? [Menelusuri melalui Google dan SO tidak membantu]


Berikan detail lebih lanjut, seperti SQL yang setara atau kodesemu yang melakukan apa yang Anda inginkan. Apa itu "id database SQLAlchemy"?
Daniel Kluev

Apakah tabel Anda memiliki kolom id?
Keith

Jawaban:


130

Kueri memiliki fungsi get yang mendukung kueri dengan kunci utama tabel, yang saya anggap demikian id.

Misalnya, untuk meminta objek dengan ID 23:

User.query.get(23)

Catatan: Seperti yang disebutkan oleh beberapa pemberi komentar dan jawaban lain, ini bukan sekadar singkatan dari "Lakukan pemfilteran kueri pada kunci utama". Bergantung pada status sesi SQLAlchemy, menjalankan kode ini dapat meminta database dan mengembalikan instance baru, atau mungkin mengembalikan instance objek yang ditanyakan sebelumnya di kode Anda tanpa benar-benar meminta database. Jika Anda belum melakukannya, pertimbangkan untuk membaca dokumentasi di Sesi SQLAlchemy untuk memahami konsekuensinya.


8
Fungsi Dapatkan juga mendukung beberapa kunci primer: YourModel.query.get((pk1, pk2)). Perhatikan tupelnya.
marc_aragones

3
The get()query fungsi benda oleh kunci utama. Jika Anda ingin membuat kueri berdasarkan id, Anda harus menetapkan idsebagai kunci utama terlebih dahulu.

46

Anda dapat menanyakan Pengguna dengan id = 1 seperti ini

session.query(User).get(1)


7

get () terkadang tidak seperti yang Anda harapkan:

jika transaksi Anda sudah selesai:

>>> 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')>

jika Anda berada dalam sebuah transaksi (get () akan memberi Anda objek hasil dalam memori tanpa query database):

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

lebih baik menggunakan ini:

>>> 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
Bagaimana perilaku ini tidak terduga?
Solomon Ucko

Maksud saya jika Anda dalam transaksi (belum session.commit) get()tampaknya memberi Anda objek hasil dalam memori (tanpa benar-benar query database), tetapi filter().first()akan selalu query database.
panda912

Apakah mungkin untuk mengubah database secara bersamaan selama transaksi? Jika tidak, penggunaan getlebih baik karena peningkatan efisiensi.
Solomon Ucko

1
seperti yang saya tahu sqlalchemy tidak dapat bekerja dengan hal-hal async (tampaknya hanya dengan gevent), dan ya, getitu lebih efisien.
panda912

Mengapa .first () berbeda dari .get () sejauh menyangkut transaksinya? Apakah .first () selalu kembali ke database? Apakah itu .get () mencari di env saat ini terlebih dahulu untuk melihat apakah ia mengetahui id itu atau sesuatu?
msouth

1

Jika Anda menggunakan tables reflectionAnda mungkin memiliki masalah dengan solusi yang diberikan. (Solusi sebelumnya di sini tidak berhasil untuk saya).

Apa yang akhirnya saya gunakan adalah:

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

( objectdiambil dengan refleksi dari database, inilah mengapa Anda perlu menggunakan .__class__)

Saya harap ini membantu.


0

Pertama, Anda harus menetapkan idsebagai kunci utama.
Kemudian Anda bisa menggunakan query.get()metode untuk meminta objek idyang sudah menjadi kunci utama.

Karena query.get()metode untuk query objek dengan kunci utama.
Disimpulkan dari dokumentasi 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)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.