Django - membatasi hasil kueri


Jawaban:


304

Kuartet Django malas. Itu berarti permintaan akan mengenai database hanya ketika Anda secara spesifik meminta hasilnya.

Jadi sampai Anda mencetak atau benar-benar menggunakan hasil kueri, Anda dapat memfilter lebih jauh tanpa akses database.

Seperti yang Anda lihat di bawah, kode Anda hanya menjalankan satu kueri sql untuk mengambil hanya 10 item terakhir.

In [19]: import logging                                 
In [20]: l = logging.getLogger('django.db.backends')    
In [21]: l.setLevel(logging.DEBUG)                      
In [22]: l.addHandler(logging.StreamHandler())      
In [23]: User.objects.all().order_by('-id')[:10]          
(0.000) SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" ORDER BY "auth_user"."id" DESC LIMIT 10; args=()
Out[23]: [<User: hamdi>]

Saya mencoba ini pada mongoDB dan dikatakan SELECT tidak didukung. Bagaimana melakukan ini di mongoDB?
winux

@ winux Karena ini adalah Django khusus, sepertinya Anda mungkin perlu melihat ke pengaturan Django untuk bekerja secara khusus dengan database tipe Mongo / NoSQL. Itu bukan pengaturan khas dalam pengalaman saya, sehubungan dengan pengaturan ORM Django standar.
pengecut anonim

38

Sebenarnya saya pikir LIMIT 10akan dikeluarkan ke basis data sehingga mengiris tidak akan terjadi di Python tetapi dalam database.

Lihat limiting-querysets untuk informasi lebih lanjut.


Perhatikan bahwa ini tidak akan berfungsi untuk kueri yang juga perlu difilter, karena Anda tidak dapat memfilter setelah mengiris.
Mike 'Pomax' Kamermans

2
Jadi saring dulu daripada mengirisnya. Terima kasih Davor untuk tautan!
Vyachez

13

Sepertinya solusi dalam pertanyaan tidak lagi berfungsi dengan Django 1.7 dan menimbulkan kesalahan: "Tidak dapat memesan ulang permintaan setelah potongan diambil"

Menurut dokumentasi https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets yang memaksa parameter “step” dari sintaks iris slice Python mengevaluasi Query. Cara kerjanya seperti ini:

Model.objects.all().order_by('-id')[:10:1]

Masih saya bertanya-tanya apakah batas dijalankan dalam SQL atau Python iris seluruh hasil array dikembalikan. Tidak ada gunanya mengambil daftar besar ke memori aplikasi.


Bahkan solusi ini tidak bekerja dengan Django> = 1,8 diuji.
sonus21

3

Iya. Jika Anda ingin mengambil subset objek terbatas, Anda bisa dengan kode di bawah ini:

Contoh:

obj=emp.objects.all()[0:10]

Awal 0 adalah opsional, jadi

obj=emp.objects.all()[:10]

Kode di atas mengembalikan 10 instance pertama.


1

Sebagai tambahan dan pengamatan terhadap jawaban-jawaban lain yang bermanfaat, perlu diperhatikan bahwa melakukan [:10]slicing akan mengembalikan 10 elemen pertama dari daftar , bukan 10 yang terakhir ...

Untuk mendapatkan 10 terakhir yang harus Anda lakukan [-10:]sebagai gantinya (lihat di sini ). Ini akan membantu Anda menghindari penggunaan order_by('-id')dengan -untuk membalikkan elemen.


1
Saya mencoba ini dan mendapat "Pengindeksan negatif tidak didukung."
bparker

@DarkCygnus Product.objects.filter(~Q(price=0))[-5:]menyebabkan saya kesalahan yang sama: "Pengindeksan negatif tidak didukung."
bersam

Ini tidak berfungsi di Django pada queryset: code.djangoproject.com/ticket/13089 Jika Anda mengonversi queryset ke daftar, ia akan berfungsi.
valem
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.