¿Cuál es la forma correcta de validar si un objeto existe en una vista de django sin devolver 404?

91

Necesito verificar si existe un objeto y devolver el objeto, luego, en base a eso, realizar acciones. ¿Cuál es la forma correcta de hacerlo sin devolver un 404?

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

if listing:
Rasiel
fuente
Rasiel, ¿puedo sugerirte que consideres aceptar la otra respuesta? Parece ser la forma correcta de hacer esto, y se ha votado un poco más que la respuesta aceptada.
Azendale
1
Puedo considerarlo, sin embargo existe se introdujo en Django 1.2 que se lanzó el 17 de mayo de 2010, si nota que mi pregunta se envió en 09 ... esta era la respuesta correcta en ese momento. Si Exists () ahora se considera la mejor manera de hacerlo, supongo que sería semánticamente correcto elegir la segunda respuesta, ¿verdad?
Rasiel
Rasiel, tiene sentido que esa fuera la respuesta correcta en ese momento. Pero los sitios de stackoverflow parecen tener tanto que ver con la construcción de un conjunto de preguntas buenas / oficiales con las mejores respuestas como los sitios están encontrando soluciones a los problemas de las personas. De ahí mi sugerencia de seleccionar lo que ahora es la respuesta "oficialmente correcta".
Azendale
El if listing:debería haber una else:.
Crónica

Respuestas:

116

No usaría el contenedor 404 si no le dan un 404. Eso es un mal uso de la intención. En su lugar, solo captura el DoesNotExist.

try:
    listing = RealEstateListing.objects.get(slug_url=slug)
except RealEstateListing.DoesNotExist:
    listing = None
ranita de hierro
fuente
+1: Sí, esta es una solución mejor que la aceptada, si no quieres el 404.
Carl Meyer
yap, esta parece ser la mejor solución
Rasiel
3
Esta solución funciona mejor que exists()si necesita hacer algo con el objeto.
SaeX
2
Me gusta agregar values_list('id', flat=True). si solo necesito ver si existelisting = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
erajuan
Lo que me resulta extraño de esta sintaxis es que RealEstateListing.DoesNotExistse refiere al modelo y no al objeto en sí. ¿Por qué no es así RealEstateListing.objects.get(slug_url=slug).DoesNotExist?
Maxim Vallee
198

También puedes hacer:

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

A veces es más claro usar try: except:bloque y otras veces una sola línea exists()hace que el código se vea más claro ... todo depende de la lógica de su aplicación.

zzart
fuente
7
esta es la mejor manera y debería tener la respuesta
Jharwood
3
Supongo que eso exists()no funciona get(), ¿verdad?
Eduard Luca
8
Tenga en cuenta que esta solución solo es válida si no va a utilizar el objeto en cuestión. De lo contrario (como en la situación de OP), está mal y es mucho más lento que la solución aceptada: si lo hace get()más tarde, enviará una segunda consulta a la base de datos.
Crónica
1
Si se está comprobando la existencia de hacer algo con el objeto (si existe), entonces yo preferiría try-exceptmás exists().
Jithin Pavithran
7
listing = RealEstateListing.objects.filter(slug_url=slug).first() 
Henrik Heino
fuente
2
Esta es la mejor solución si necesita usar el objeto potencial más adelante, ya que solo requiere una asignación y evita tener que usar un bloque try / except. Tenga en cuenta que puede probar la existencia más tarde simplemente conif listing:
Michael Hays
Evitar try / except es una mala práctica. Uno de los aspectos más importantes del Desarrollo de Software es la disponibilidad para controlar Excepciones, esto para poder brindar una buena experiencia de usuario. Hágale saber a la gente cuando algo no esté funcionando correctamente. Segundo; si desea probar la existencia de un QuerySet, use .exists (); de lo contrario, es un objeto. Prueba la existencia con su clave principal .... if object.pk: // ejecutar código () Esta consulta es mucho más rápida que recuperar todos los datos del objeto. Solo quieres saber si existe.
Wolfgang Leon
2
Ya había una solución usando try / except y .exists(). Creo que es una buena idea en SO tener múltiples respuestas diferentes sobre cómo hacer las cosas. Quizás esto sea mejor para aquellos que también quieran usar el objeto si existe. No haría ninguna regla si se debe evitar try / except o no. A veces es bueno y otras es malo, por ejemplo, si solo desea hacer un código muy compacto.
Henrik Heino
0

Lo haría tan simple como sigue:

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

No veo la necesidad de probar / atrapar. Si hay potencialmente varios objetos en el resultado, utilice primero () como lo muestra el usuario Henrik Heino

Greg Holst
fuente
A menos que haga un .first () en el conjunto de consultas o un .first () en el condicional, esto siempre devolverá True.
B.Adler