วิธีที่ถูกต้องในการตรวจสอบว่าวัตถุมีอยู่ในมุมมอง django โดยไม่ส่งคืน 404 อย่างไร


93

ฉันต้องการตรวจสอบว่ามีวัตถุอยู่หรือไม่และส่งคืนวัตถุจากนั้นขึ้นอยู่กับการดำเนินการนั้น วิธีใดที่ถูกต้องในการทำโดยไม่ส่งคืน 404

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

if listing:

Rasiel ฉันขอแนะนำให้คุณพิจารณายอมรับคำตอบอื่นได้ไหม ดูเหมือนว่าจะเป็นวิธีที่ถูกต้องในการทำเช่นนี้และได้รับการโหวตมากกว่าคำตอบที่ได้รับการยอมรับเล็กน้อย
Azendale

1
ฉันสามารถพิจารณาได้ แต่มีอยู่ใน Django 1.2 ซึ่งเผยแพร่เมื่อวันที่ 17 พฤษภาคม 2010 หากคุณสังเกตเห็นว่าคำถามของฉันถูกส่งใน 09 ... นี่คือคำตอบที่ถูกต้องในเวลานั้น ถ้าตอนนี้มีอยู่ () ถือเป็นวิธีที่ดีที่สุดฉันเดาว่ามันจะถูกต้องตามความหมายในการเลือกคำตอบที่สองใช่ไหม
Rasiel

Rasiel มันสมเหตุสมผลแล้วที่เป็นคำตอบที่ถูกต้องในตอนนั้น แต่ไซต์ stackoverflow ดูเหมือนจะเกี่ยวกับการสร้างชุดคำถามที่ดี / เป็นทางการพร้อมคำตอบที่ดีที่สุดเนื่องจากไซต์กำลังหาวิธีแก้ปัญหาของผู้คน ดังนั้นคำแนะนำของฉันในการเลือกคำตอบที่ "ถูกต้องอย่างเป็นทางการ" ในตอนนี้
Azendale

ควรจะเป็นif listing: else:
โครเนียล

คำตอบ:


117

ฉันจะไม่ใช้กระดาษห่อ 404 ถ้าคุณไม่ได้รับ 404 นั่นเป็นการใช้เจตนาในทางที่ผิด เพียงจับ DoesNotExist แทน

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

+1: ใช่นี่เป็นทางออกที่ดีกว่าวิธีที่ยอมรับถ้าคุณไม่ต้องการ 404
Carl Meyer

อ๋อดูเหมือนจะเป็นทางออกที่ดีกว่า
Rasiel

3
วิธีนี้ใช้ได้ผลดีกว่าexists()ถ้าคุณต้องทำอะไรกับวัตถุ
SaeX

2
values_list('id', flat=True)ผมชอบที่จะเพิ่ม ถ้าฉันต้องการเพียงแค่ดูว่ามีอยู่หรือไม่listing = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
erajuan

สิ่งที่ฉันพบว่าแปลกเกี่ยวกับไวยากรณ์นี้RealEstateListing.DoesNotExistคือการอ้างอิงถึงโมเดลไม่ใช่ตัววัตถุ ทำไมมันไม่RealEstateListing.objects.get(slug_url=slug).DoesNotExist?
Maxim Vallee

200

คุณยังสามารถทำ:

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

บางครั้งมันชัดเจนกว่าที่จะใช้try: except:บล็อกและบางครั้งซับเดียวexists()ทำให้โค้ดดูชัดเจนขึ้น ... ทั้งหมดขึ้นอยู่กับตรรกะแอปพลิเคชันของคุณ


8
.exists () เร็วกว่า: docs.djangoproject.com/en/dev/ref/models/querysets/#exists
fjsj

7
นี่เป็นวิธีที่ดีกว่าและควรมีคำตอบ
Jharwood

3
ฉันคิดว่ามันใช้exists()ไม่ได้get()ใช่มั้ย?
Eduard Luca

9
โปรดทราบว่าวิธีนี้ใช้ได้เฉพาะในกรณีที่คุณไม่ได้ใช้วัตถุที่เป็นปัญหา มิฉะนั้น (เช่นในสถานการณ์ OPs) จะผิดและช้ากว่าโซลูชันที่ยอมรับมาก: หากคุณดำเนินการในget()ภายหลังระบบจะส่งแบบสอบถามที่สองไปยังฐานข้อมูล
โครเนียล

1
หากคุณกำลังตรวจสอบการดำรงอยู่จะทำอะไรกับวัตถุ (ถ้ามี) แล้วผมจะชอบมากกว่าtry-except exists()
Jithin Pavithran

7
listing = RealEstateListing.objects.filter(slug_url=slug).first() 

2
นี่เป็นวิธีแก้ปัญหาที่ดีที่สุดหากคุณจำเป็นต้องใช้วัตถุที่มีศักยภาพในภายหลังเนื่องจากต้องใช้การมอบหมายเพียงครั้งเดียวและหลีกเลี่ยงการใช้บล็อก try / except โปรดทราบว่าคุณสามารถทดสอบการดำรงอยู่ในภายหลังได้ง่ายๆด้วยif listing:
Michael Hays

การหลีกเลี่ยงการลอง / ยกเว้นเป็นการปฏิบัติที่ไม่ดี สิ่งที่สำคัญที่สุดประการหนึ่งของการพัฒนาซอฟต์แวร์คือความพร้อมในการควบคุมข้อยกเว้นซึ่งจะสามารถมอบประสบการณ์การใช้งานที่ดีแก่ผู้ใช้ได้ แจ้งให้ผู้อื่นทราบเมื่อมีบางอย่างทำงานไม่ถูกต้อง ประการที่สอง; หากคุณต้องการทดสอบการมีอยู่ของ QuerySet ให้ใช้ .exists () มิฉะนั้นจะเป็นวัตถุ ทดสอบการมีอยู่ด้วยคีย์หลักของพวกเขา .... ถ้า object.pk: // รันโค้ด () เคียวรีนี้เร็วกว่าการดึงข้อมูลทั้งหมดของอ็อบเจ็กต์ คุณแค่อยากรู้ว่ามีอยู่จริงไหม
Wolfgang Leon

2
มีวิธีแก้ปัญหาอยู่แล้วโดยใช้ try / except และ.exists(). ฉันคิดว่ามันเป็นความคิดที่ดีใน SO ที่จะมีคำตอบที่แตกต่างกันในการทำสิ่งต่างๆ อาจจะดีกว่าสำหรับผู้ที่ต้องการใช้วัตถุด้วยหากมีอยู่ ฉันจะไม่ทำกฎใด ๆ หากพยายาม / ยกเว้นควรหลีกเลี่ยงหรือไม่ บางครั้งก็ดีและบางครั้งก็ไม่ดีเช่นหากคุณต้องการสร้างโค้ดที่กะทัดรัดมาก
Henrik Heino

0

ฉันจะทำง่ายๆดังนี้:

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

ฉันไม่เห็นความจำเป็นในการลอง / จับ หากผลลัพธ์มีหลายวัตถุให้ใช้ first () ตามที่แสดงโดยผู้ใช้ Henrik Heino


เว้นแต่คุณจะทำ. first () ในชุดแบบสอบถามหรือ. first () ในเงื่อนไขสิ่งนี้จะส่งกลับ True เสมอ
บีแอดเลอร์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.