Was ist der richtige Weg, um zu überprüfen, ob ein Objekt in einer Django-Ansicht vorhanden ist, ohne 404 zurückzugeben?

91

Ich muss überprüfen, ob ein Objekt vorhanden ist, und das Objekt zurückgeben und dann basierend darauf Aktionen ausführen. Was ist der richtige Weg, um einen 404 zurückzugeben?

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

if listing:
Rasiel
quelle
Rasiel, kann ich vorschlagen, dass Sie die andere Antwort akzeptieren? Es scheint der richtige Weg zu sein, dies zu tun, und es wurde viel mehr als die akzeptierte Antwort positiv bewertet.
Azendale
1
Ich kann es in Betracht ziehen, jedoch existiert es in Django 1.2, das am 17. Mai 2010 veröffentlicht wurde. Wenn Sie bemerken, dass meine Frage im Jahr 09 eingereicht wurde ... war dies die richtige Antwort zu der Zeit. Wenn Exists () jetzt als der beste Weg angesehen wird, wäre es semantisch korrekt, die zweite Antwort zu wählen, oder?
Rasiel
Rasiel, es macht Sinn, dass das damals die richtige Antwort war. Bei den Stackoverflow-Sites geht es jedoch anscheinend genauso darum, eine Reihe guter / offizieller Fragen mit den besten Antworten zu erstellen, wie die Sites nach Lösungen für die Probleme der Menschen suchen. Daher mein Vorschlag, die jetzt "offiziell korrekte" Antwort auszuwählen.
Azendale
Das if listing:sollte ein sein else:.
Chronial

Antworten:

116

Ich würde den 404-Wrapper nicht verwenden, wenn Sie keinen 404 erhalten. Das ist ein Missbrauch der Absicht. Fangen Sie stattdessen einfach die DoesNotExist.

try:
    listing = RealEstateListing.objects.get(slug_url=slug)
except RealEstateListing.DoesNotExist:
    listing = None
Eisenfrosch
quelle
+1: Ja, dies ist eine bessere Lösung als die akzeptierte, wenn Sie die 404 nicht wollen.
Carl Meyer
Ja, dies scheint die bessere Lösung zu sein
Rasiel
3
Diese Lösung funktioniert besser, als exists()wenn Sie etwas mit dem Objekt tun müssen.
SaeX
2
Ich mag hinzufügen values_list('id', flat=True). wenn ich nur sehen muss, ob es existiertlisting = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
erajuan
Was ich an dieser Syntax seltsam finde, ist, dass sie RealEstateListing.DoesNotExistsich auf das Modell bezieht und nicht auf das Objekt selbst. Warum ist es nicht RealEstateListing.objects.get(slug_url=slug).DoesNotExist?
Maxim Vallee
197

Sie können auch tun:

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

Manchmal ist es klarer, try: except:Block zu verwenden , und manchmal macht ein Einzeiler exists()den Code klarer ... alles hängt von Ihrer Anwendungslogik ab.

zzart
quelle
7
Dies ist der bessere Weg und sollte die Antwort haben
Jharwood
3
Ich gehe davon aus, dass exists()das nicht funktioniert get(), oder?
Eduard Luca
8
Beachten Sie, dass diese Lösung nur gültig ist, wenn Sie das betreffende Objekt nicht verwenden. Andernfalls (wie in der OP-Situation) ist es falsch und viel langsamer als die akzeptierte Lösung: Wenn Sie dies get()später tun , wird eine zweite Abfrage an die Datenbank gesendet.
Chronial
1
Wenn Sie die Existenz Prüfung etwas mit dem Objekt zu tun (falls vorhanden), dann werde ich es vorziehen , try-exceptüber exists().
Jithin Pavithran
7
listing = RealEstateListing.objects.filter(slug_url=slug).first() 
Henrik Heino
quelle
2
Dies ist die beste Lösung, wenn Sie das potenzielle Objekt später verwenden müssen, da nur eine Zuweisung erforderlich ist und die Verwendung eines Try / Except-Blocks vermieden wird. Beachten Sie, dass Sie später einfach mitif listing:
Michael Hays
Vermeiden / Ausnehmen ist eine schlechte Praxis. Einer der wichtigsten Aspekte der Softwareentwicklung ist die Verfügbarkeit zur Steuerung von Ausnahmen, um eine gute Benutzererfahrung bieten zu können. Lassen Sie die Leute wissen, wenn etwas nicht richtig funktioniert. Zweite; Wenn Sie die Existenz eines QuerySet testen möchten, verwenden Sie .exists (), andernfalls handelt es sich um ein Objekt. Testen Sie die Existenz mit ihrem Primärschlüssel .... if object.pk: // run code () Diese Abfrage ist viel schneller als das Abrufen aller Daten des Objekts. Sie möchten nur wissen, ob es existiert.
Wolfgang Leon
2
Es gab bereits Lösungen mit try / Except und .exists(). Ich denke, es ist eine gute Idee in SO, mehrere unterschiedliche Antworten zu haben, wie man Dinge macht. Vielleicht ist dies besser für diejenigen, die das Objekt auch verwenden möchten, wenn es existiert. Ich würde keine Regeln aufstellen, ob try / without vermieden werden sollte oder nicht. Manchmal ist es gut und manchmal ist es schlecht, wenn Sie nur sehr kompakten Code erstellen möchten.
Henrik Heino
0

Ich würde es so einfach wie folgt machen:

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

Ich sehe keine Notwendigkeit für Versuch / Fang. Wenn das Ergebnis möglicherweise mehrere Objekte enthält, verwenden Sie zuerst (), wie vom Benutzer Henrik Heino gezeigt

Greg Holst
quelle
Sofern Sie nicht eine .first () für den Abfragesatz oder eine .first () für die Bedingung ausführen, wird immer True zurückgegeben.
B.Adler