2015-10-14 9 views
6

Quando ho voglia di selezionare gli oggetti con una funzione get() comeCome gestire "query corrispondente non esiste" quando ottiene un oggetto

personalProfile = World.objects.get(ID=personID) 

Se ottenere la funzione non restituisce trovare un valore, un " la ricerca corrispondente non esiste. " errore si verifica

Se non ho bisogno di questo errore, userò prova e tranne la funzione

try: 
    personalProfile = World.objects.get(ID=personID) 
except: 
    pass 

ma credo che questo non è il modo migliore da quando io uso

except: 
     pass 

Si prega di raccomandare alcuni campione di idea o codice per combattere con questo numero

risposta

10

Questo dipende da cosa vuoi fare se non esiste ..

Theres get_object_or_404:

chiamate get() su un determinato gestore del modello, ma solleva Http404 invece di eccezione DoesNotExist del modello.

get_object_or_404(World, ID=personID) 

che è molto vicino alla prova, tranne il codice che attualmente fanno.

theres Altrimenti get_or_create:

personalProfile, created = World.objects.get_or_create(ID=personID) 

Anche se, se si sceglie di continuare con il vostro approccio attuale, almeno assicurarsi che l'eccezione è localizzato al di errore corretto e poi fare qualcosa con quella, se necessario

try: 
    personalProfile = World.objects.get(ID=personID) 
except MyModel.DoesNotExist: 
    raise Http404("No MyModel matches the given query.") 

Il try sopra/tranne la maniglia è simile a quello che si trova nella documentazione per get_object_or_404 ...

+1

Grazie per questo aiuto. Ho provato questo e ricevendo l'errore perché non ho importato un Http404 Quindi correggi questo da "da django.http import Http404" e perfetto! –

2

Una funzione get_or_none() è stata proposed, multipletimes ora. L'avviso di rifiuto è inversione di funzione, con cui potresti o meno essere d'accordo. La funzionalità è presente - con semantica leggermente diversa - nel metodo di queryset first().

Ma andiamo con ordine:

Il manager lancia World.DoesNotExist, una sottoclasse specializzata di ObjectDoesNotExist quando un oggetto World non è stato trovato:

try: 
    personalProfile = World.objects.get(ID=personID) 
except World.DoesNotExist: 
    pass 

C'è anche get_object_or_404() che solleva un'eccezione Http404 quando l'oggetto era non trovato.

È anche possibile eseguire il rollover del proprio get_or_none(). Una possibile applicazione potrebbe essere:

def get_or_none(queryset, *args, **kwargs): 
    try: 
     return queryset.get(*args, **kwargs) 
    except ObjectDoesNotExist: 
     return None 

Si noti che questo solleva ancora MultipleObjectsReturned quando viene trovato più di un oggetto corrispondente.Se si vuole sempre il primo oggetto indipendentemente da tutti gli altri, è possibile semplificare utilizzando first(), che restituisce None quando il set di query è vuota:

def get_or_none(queryset, *args, **kwargs): 
    return queryset.filter(*args, **kwargs).first() 

Nota tuttavia, per far funzionare in modo affidabile, è necessario un giusto ordine per gli oggetti , perché in presenza di più oggetti first() potrebbe essere non deterministico (probabilmente restituisce il primo oggetto dall'indice del database utilizzato per filtrare la query e né gli indici né le tabelle sottostanti devono essere ordinati o hanno anche un ordine ripetibile).

Utilizzare entrambi, tuttavia, solo quando l'utilizzo dell'oggetto da recuperare è strettamente facoltativo per l'ulteriore flusso del programma. Quando il mancato recupero di un oggetto è un errore, utilizzare get_object_or_404(). Quando un oggetto deve essere creato quando non esiste, utilizzare get_or_create(). In questi casi, entrambi sono più adatti a semplificare il flusso del programma.

+3

Il metodo ['first()'] (https://docs.djangoproject.com/en/1.8/ref/models/querysets/#first) aggiunto in Django 1.6 è molto simile a 'get_or_none'. Nota che non stai gestendo 'MultipleObjectsReturned' nel tuo metodo. Il metodo 'first()' prende semplicemente il primo elemento e ignora il resto. – Alasdair

+0

@Alasdair La mancata gestione di 'MultipleObjectsReturned' è piuttosto intenzionale. Comunque, sì, 'get_or_none()' può essere semplificato per usare 'first()'. Hai controllato in che modo ciò influisce sulle query SQL generate? – dhke

+1

Il mio punto è che, sebbene i biglietti a cui sei collegato siano stati chiusi e non vengano risolti, alla fine è stata aggiunta la funzione, ma con un nome diverso. 'MyModel.objects.filter (** kwargs) .first()' fa la stessa cosa 'get_object_or_none (MyModel, ** kwargs)', a meno che non ti interessi davvero 'MultipleObjectsReturned' (che mi aspetto la maggior parte del tempo che tu non usi) t). Non ho esaminato l'SQL, ma mi aspetto che sarà abbastanza simile, forse con alcune differenze con 'limite'. – Alasdair

Problemi correlati