Qual è il modo giusto per convalidare se un oggetto esiste in una visualizzazione django senza restituire 404?


91

Devo verificare se un oggetto esiste e restituire l'oggetto, quindi in base a quello eseguire azioni. Qual è il modo giusto per farlo senza restituire un 404?

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

if listing:

Rasiel, posso suggerirle di considerare di accettare l'altra risposta? Sembra essere il modo corretto per farlo, ed è stato votato un po 'più della risposta accettata.
Azendale

1
Posso considerarlo, tuttavia esiste è stato introdotto in Django 1.2 che è stato rilasciato il 17 maggio 2010, Se noti che la mia domanda è stata presentata in 09 ... questa era la risposta corretta al momento. Se Exists () è ora considerato il modo migliore per farlo, immagino che sarebbe semanticamente corretto scegliere la seconda risposta, giusto?
Rasiel

Rasiel, ha senso che quella fosse la risposta corretta al momento. Ma i siti stackoverflow sembrano essere tanto sulla creazione di una serie di buone domande / ufficiali con le migliori risposte quanto i siti stanno trovando soluzioni ai problemi delle persone. Da qui il mio suggerimento di selezionare quella che ora è la risposta "ufficialmente corretta".
Azendale

Il if listing:dovrebbe essere un else:.
Cronologia

Risposte:


116

Non userei il wrapper 404 se non ti viene fornito un 404. Questo è un uso improprio dell'intenzione. Prendi invece DoesNotExist.

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

+1: Sì, questa è una soluzione migliore di quella accettata, se non vuoi il 404.
Carl Meyer

yap, questa sembra essere la soluzione migliore
Rasiel

3
Questa soluzione funziona meglio che exists()se hai bisogno di fare qualcosa con l'oggetto.
SaeX

2
Mi piace aggiungere values_list('id', flat=True). se ho bisogno di vedere solo se esistelisting = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
erajuan

Quello che trovo strano di questa sintassi è che RealEstateListing.DoesNotExistsi riferisce al modello e non all'oggetto stesso. Perché non lo è RealEstateListing.objects.get(slug_url=slug).DoesNotExist?
Maxim Vallee

198

Puoi anche fare:

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

A volte è più chiaro usare try: except:block e altre volte one-liner exists()rende il codice più chiaro ... tutto dipende dalla logica dell'applicazione.



7
questo è il modo migliore e dovrebbe avere la risposta
Jharwood

3
Suppongo che exists()non funzioni con get(), giusto?
Eduard Luca

8
Nota che questa soluzione è valida solo se non intendi utilizzare l'oggetto in questione. Altrimenti (come nella situazione degli OP) è sbagliato e molto più lento della soluzione accettata: se ne fai una get()successiva, invierà una seconda query al database.
Cronologia

1
Se si sta verificando l'esistenza di fare qualcosa con l'oggetto (se esiste), allora io preferisco try-exceptsopra exists().
Jithin Pavithran

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

2
Questa è la soluzione migliore se è necessario utilizzare il potenziale oggetto in un secondo momento, poiché richiede solo un'assegnazione ed evita di dover utilizzare un blocco try / tranne. Nota che puoi testare l'esistenza in seguito semplicemente conif listing:
Michael Hays

Evitare di provare / tranne è una cattiva pratica. Uno degli aspetti più importanti dello sviluppo software è la disponibilità a controllare le eccezioni, questo per poter fornire una buona esperienza utente. Fai sapere alle persone quando qualcosa non funziona correttamente. Secondo; se vuoi testare l'esistenza di un QuerySet usa .exists () altrimenti è un oggetto. Verifica l'esistenza con la loro chiave primaria .... if object.pk: // run code () Questa query è molto più veloce del recupero di tutti i dati dell'oggetto. Vuoi solo sapere se esiste.
Wolfgang Leon,

2
C'era già una soluzione che utilizzava try / tranne e .exists(). Penso che sia una buona idea in SO avere più risposte diverse su come fare le cose. Forse questo è meglio per coloro che vogliono utilizzare anche l'oggetto se esiste. Non stabilirei alcuna regola se try / tranne dovesse essere evitato o meno. A volte va bene, a volte va male, ad esempio se vuoi solo creare codice molto compatto.
Henrik Heino

0

Lo farei semplicemente come segue:

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

Non vedo la necessità di provare / catturare. Se ci sono potenzialmente diversi oggetti nel risultato, usa first () come mostrato dall'utente Henrik Heino


A meno che tu non esegua un .first () nel set di query o un .first () nel condizionale, questo restituirà sempre True.
B.Adler
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.