2010-12-04 9 views
32

Cada vez que hago esto:¿Cuál es la mejor manera de manejar objects.get de Django?

thepost = Content.objects.get(name="test") 

Siempre genera un error cuando no se encuentra nada. ¿Cómo lo manejo?

+0

Véase también [QuerySet.get] (http://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.QuerySet.get) –

+2

Así se supone que es trabajo. ¿Cuál es tu pregunta? ¿Cómo escribir una declaración 'try'? –

Respuesta

56
from django.core.exceptions import ObjectDoesNotExist 

try: 
    thepost = Content.objects.get(name="test") 
except ObjectDoesNotExist: 
    thepost = None 

Escribo esto de memoria, por lo que no estoy seguro de la excepción.

+8

En este caso, la excepción es 'Content.DoesNotExist', y esta estructura de código es útil si desea continuar incluso si no se puede encontrar el objeto (es decir, no arrojar un error 404 como en mi ejemplo). –

20

A menudo, es más útil el uso de la función de acceso directo Django get_object_or_404 lugar de la API directamente:

from django.shortcuts import get_object_or_404 

thepost = get_object_or_404(Content, name='test') 

Bastante obviamente, esto va a lanzar un error 404 si el objeto no se puede encontrar, y el código se continuar si es exitoso

7

captura la excepción

try: 
    thepost = Content.objects.get(name="test") 
except Content.DoesNotExist: 
    thepost = None 

, alternativamente, puede filtrar, que devolverá una lista vacía si nada se compara con

posts = Content.objects.filter(name="test") 
if posts: 
    # do something with posts[0] and see if you want to raise error if post > 1 
+0

¿por qué asignar un Queryset vacío cuando get() solo generará una excepción? La primera aproximación try/catch es mucho mejor – ppetrid

+0

Normalmente, el uso de excepciones para el "flujo de trabajo" normal no es una buena práctica. En este ejemplo, es bastante fácil de entender, pero si comienza a usar excepciones para controlar una aplicación, será difícil de mantener/depurar. – mrmuggles

+0

@mrmuggles No estoy de acuerdo, Exception podría ser una muy buena forma de estructurar tu código, e..g 'para el plugin en complementos; tratar; processed_text = plugin.process (texto); excepto Exception1 ,: hacer algo Exception 2; hacer algo 'no hay alternativa más fácil a esto, y en este caso específico tiene mucho sentido, ¿podrías cambiar dict.has_key antes de acceder al elemento o simplemente acceder al elemento y atrapar KeyError? –

12

También puede coger un DoesNotExist genérico. De acuerdo con los documentos en http://docs.djangoproject.com/en/dev/ref/models/querysets/

from django.core.exceptions import ObjectDoesNotExist 
try: 
    e = Entry.objects.get(id=3) 
    b = Blog.objects.get(id=1) 
except ObjectDoesNotExist: 
    print "Either the entry or blog doesn't exist." 
0

Criar a un Http404 exception funciona muy bien:

from django.http import Http404 

def detail(request, poll_id): 
    try: 
     p = Poll.objects.get(pk=poll_id) 
    except Poll.DoesNotExist: 
     raise Http404 
    return render_to_response('polls/detail.html', {'poll': p}) 
+1

Esto funciona solo si el objeto Poll representa el todo ver. Si solo intenta consultar un objeto que aterrizará en el medio de una página, no desea devolver 404 para toda la vista. – shacker

2

Manejo de excepciones en diferentes puntos de su punto de vista podría ser realmente cumbersome..What sobre la definición de un Gestor personalizado Modelo, en el models.py archivo, como

class ContentManager(model.Manager): 
    def get_nicely(self, **kwargs): 
     try: 
      return self.get(kwargs) 
     except(KeyError, Content.DoesNotExist): 
      return None 

y luego incluirlo en la clase de contenido Modelo

class Content(model.Model): 
    ... 
    objects = ContentManager() 

De esta manera puede ser fácilmente tratada en los puntos de vista, es decir,

post = Content.objects.get_nicely(pk = 1) 
if post != None: 
    # Do something 
else: 
    # This post doesn't exist 
5

Otra manera de escribir:

try: 
    thepost = Content.objects.get(name="test") 
except Content.DoesNotExist: 
    thepost = None 

es simplemente:

thepost = Content.objects.filter(name="test").first() 

Tenga en cuenta que la dos no son estrictamente lo mismo. El método Manager get no solo generará una excepción en el caso , no hay registro que está buscando, pero también cuando se encuentran registros múltiples. El uso de first cuando hay más de un registro puede fallar la lógica de su negocio al devolver el primer registro.

Cuestiones relacionadas