Seringkali saya mendapati diri saya ingin mendapatkan objek pertama dari queryset di Django, atau kembali None
jika tidak ada. Ada banyak cara untuk melakukan ini yang semuanya berfungsi. Tapi saya bertanya-tanya mana yang paling performan.
qs = MyModel.objects.filter(blah = blah)
if qs.count() > 0:
return qs[0]
else:
return None
Apakah ini menghasilkan dua panggilan basis data? Itu sepertinya boros. Apakah ini lebih cepat?
qs = MyModel.objects.filter(blah = blah)
if len(qs) > 0:
return qs[0]
else:
return None
Pilihan lain adalah:
qs = MyModel.objects.filter(blah = blah)
try:
return qs[0]
except IndexError:
return None
Ini menghasilkan panggilan database tunggal, yang bagus. Tetapi membutuhkan membuat objek pengecualian banyak waktu, yang merupakan hal yang sangat intensif memori untuk dilakukan ketika semua yang Anda butuhkan adalah tes-sepele sepele.
Bagaimana saya bisa melakukan ini hanya dengan satu panggilan basis data dan tanpa mengaduk memori dengan objek pengecualian?
len()
pada queryset, selalu gunakan.count()
.first()
danlast()
kenyamanan: docs.djangoproject.com/en/dev/ref/models/querysets/#firstJawaban:
Django 1.6 (dirilis November 2013) memperkenalkan metode kenyamanan
first()
danlast()
yang menelan pengecualian yang dihasilkan dan kembaliNone
jika queryset tidak mengembalikan objek.sumber
first()
danlast()
memberlakukanORDER BY
klausa pada kueri. Ini akan membuat hasilnya deterministik tetapi kemungkinan besar akan memperlambat permintaan.Jawaban yang benar adalah
Yang dapat digunakan di:
Anda tidak ingin mengubahnya menjadi daftar karena akan memaksa panggilan database penuh dari semua catatan. Lakukan saja di atas dan itu hanya akan menarik yang pertama. Anda bahkan dapat menggunakan
.order_by
untuk memastikan Anda mendapatkan yang pertama Anda inginkan.Pastikan untuk menambahkan
.get()
atau Anda akan mendapatkan QuerySet kembali dan bukan objek.sumber
Entry.objects.all()[0]
??sumber
LIMIT 1
kueri, dan saya tidak tahu bahwa Anda bisa melakukan yang lebih baik dari ini. Namun, secara internal__nonzero__
diQuerySet
diimplementasikan sebagaitry: iter(self).next() except StopIteration: return false...
sehingga tidak luput pengecualian.QuerySet.__nonzero__()
tidak pernah dipanggil karenaQuerySet
dikonversi kelist
sebelum memeriksa kebenaran. Pengecualian lain mungkin masih terjadi.StopIteration
pengecualian.__iter__
untuk mendapatkan objek iterator baru dan memanggilnext
metode itu sampaiStopIteration
dibuang. Jadi secara pasti akan ada pengecualian di suatu tempat;)Sekarang, di Django 1.9 Anda memiliki
first()
metode untuk kueryset.Ini adalah cara yang lebih baik daripada
.get()
atau[0]
karena itu tidak memberikan pengecualian jika queryset kosong, Therafore, Anda tidak perlu memeriksa menggunakanexists()
sumber
Jika Anda berencana untuk mendapatkan elemen pertama sering - Anda dapat memperluas QuerySet ke arah ini:
Tentukan model seperti ini:
Dan gunakan seperti ini:
sumber
Ini bisa bekerja juga:
jika kosong, maka mengembalikan daftar kosong, jika tidak mengembalikan elemen pertama di dalam daftar.
sumber
Bisa seperti ini
atau
sumber
Anda harus menggunakan metode Django, seperti ada. Ada di sana bagi Anda untuk menggunakannya.
sumber
Sejak django 1.6 Anda dapat menggunakan filter () dengan metode first () seperti:
sumber