Apa cara yang benar untuk memvalidasi jika sebuah obyek ada dalam tampilan django tanpa mengembalikan 404?

93

Saya perlu memverifikasi jika suatu objek ada dan mengembalikan objek tersebut, kemudian berdasarkan itu melakukan tindakan. Apa cara yang benar untuk melakukannya tanpa mengembalikan 404?

try:
    listing = RealEstateListing.objects.get(slug_url = slug)
except:
    listing = None

if listing:
Rasiel
sumber
Rasiel, dapatkah saya menyarankan agar Anda mempertimbangkan untuk menerima jawaban lain? Tampaknya ini cara yang benar untuk melakukan ini, dan telah diberi suara positif lebih banyak daripada jawaban yang diterima.
Azendale
1
Saya dapat mempertimbangkannya, namun ada diperkenalkan di Django 1.2 yang dirilis 17 Mei 2010, Jika Anda perhatikan pertanyaan saya diajukan pada 09 ... ini adalah jawaban yang benar pada saat itu. Jika Exists () sekarang dianggap sebagai cara terbaik untuk melakukannya, saya rasa akan benar secara semantik memilih jawaban kedua, bukan?
Rasiel
Rasiel, masuk akal kalau itu jawaban yang benar saat itu. Tetapi situs stackoverflow tampaknya lebih banyak tentang membangun serangkaian pertanyaan baik / resmi dengan jawaban terbaik karena situs tersebut menemukan solusi untuk masalah orang. Oleh karena itu, saran saya untuk memilih apa yang sekarang menjadi jawaban yang "secara resmi benar".
Azendale
Ini if listing:harus menjadi else:.
Kronis

Jawaban:

117

Saya tidak akan menggunakan pembungkus 404 jika Anda tidak diberi 404. Itu adalah penyalahgunaan maksud. Tangkap saja DoesNotExist sebagai gantinya.

try:
    listing = RealEstateListing.objects.get(slug_url=slug)
except RealEstateListing.DoesNotExist:
    listing = None
ironfroggy
sumber
+1: Ya, ini adalah solusi yang lebih baik daripada yang diterima, jika Anda tidak menginginkan 404.
Carl Meyer
ya, ini tampaknya menjadi solusi yang lebih baik
Rasiel
3
Solusi ini bekerja lebih baik daripada exists()jika Anda perlu melakukan sesuatu dengan objek.
SaeX
2
Saya suka menambahkan values_list('id', flat=True). jika saya hanya perlu melihat apakah adalisting = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
erajuan
Yang saya anggap aneh tentang sintaks ini adalah yang RealEstateListing.DoesNotExistmerujuk pada model, dan bukan objek itu sendiri. Mengapa tidak RealEstateListing.objects.get(slug_url=slug).DoesNotExist?
Maxim Vallee
200

Anda juga bisa melakukan:

if not RealEstateListing.objects.filter(slug_url=slug).exists():
    # do stuff...

Terkadang lebih jelas untuk menggunakan try: except:blokir dan di lain waktu one-liner exists()membuat kode terlihat lebih jelas ... semua tergantung pada logika aplikasi Anda.

zzart
sumber
7
ini adalah cara yang lebih baik dan seharusnya memiliki jawabannya
Jharwood
3
Saya berasumsi bahwa exists()itu tidak berhasil get(), bukan?
Eduard Luca
9
Perhatikan bahwa solusi ini hanya valid jika Anda tidak akan menggunakan objek yang dimaksud. Jika tidak (seperti dalam situasi OP) itu salah dan jauh lebih lambat daripada solusi yang diterima: Jika Anda melakukannya get()nanti, itu akan mengirim kueri kedua ke database.
Kronis
1
Jika Anda memeriksa keberadaan untuk melakukan sesuatu dengan objek (jika ada), maka saya akan memilih try-exceptlebih exists().
Jithin Pavithran
7
listing = RealEstateListing.objects.filter(slug_url=slug).first() 
Henrik Heino
sumber
2
Ini adalah solusi terbaik jika Anda perlu menggunakan objek potensial nanti, karena ini hanya memerlukan satu tugas, dan menghindari penggunaan blok coba / kecuali. Perhatikan bahwa Anda dapat menguji keberadaannya nanti hanya denganif listing:
Michael Hays
Menghindari mencoba / kecuali adalah praktik yang buruk. Salah satu aspek terpenting dari Pengembangan Perangkat Lunak adalah ketersediaan untuk mengontrol Pengecualian, ini untuk dapat memberikan pengalaman pengguna yang baik. Beri tahu orang-orang jika ada sesuatu yang tidak berfungsi dengan baik. Kedua; jika Anda ingin menguji keberadaan QuerySet gunakan .exists () sebaliknya adalah sebuah objek. Uji keberadaan dengan kunci utama .... if object.pk: // run code () Kueri ini jauh lebih cepat daripada mengambil semua data objek. Anda hanya ingin tahu apakah ada.
Wolfgang Leon
2
Sudah ada solusi menggunakan try / kecuali dan .exists(). Saya pikir itu adalah ide yang baik dalam SO memiliki beberapa jawaban berbeda bagaimana melakukan sesuatu. Mungkin ini lebih baik bagi mereka yang juga ingin menggunakan objek tersebut jika ada. Saya tidak akan membuat aturan apa pun jika mencoba / kecuali harus dihindari atau tidak. Terkadang bagus, dan terkadang buruk misalnya jika Anda hanya ingin membuat kode yang sangat ringkas.
Henrik Heino
0

Saya akan melakukannya sesederhana berikut:

listing = RealEstateListing.objects.filter(slug_url=slug)
if listing:
    # do stuff

Saya tidak merasa perlu mencoba / menangkap. Jika ada potensi beberapa objek dalam hasil, maka gunakan first () seperti yang ditunjukkan oleh pengguna Henrik Heino

Greg Holst
sumber
Kecuali Anda melakukan .first () pada set kueri atau .first () dalam kondisional, ini akan selalu mengembalikan True.
B. Adler