Error de Django: la consulta coincidente no existe

92

Finalmente lancé mi proyecto al nivel de producción y de repente tengo algunos problemas con los que nunca tuve que lidiar en la fase de desarrollo.

Cuando los usuarios publican algunas acciones, a veces aparece el siguiente error.

Traceback (most recent call last):

  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)

  File "home/ubuntu/server/opineer/comments/views.py", line 103, in comment_expand
    comment = Comment.objects.get(pk=comment_id)

  File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 131, in get
    return self.get_query_set().get(*args, **kwargs)

  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 366, in get
    % self.model._meta.object_name)

DoesNotExist: Comment matching query does not exist

Lo que realmente me frustra es que el proyecto funciona bien en el entorno local y, además, el objeto de consulta coincidente SI existe en la base de datos.

Ahora sospecho que el usuario está accediendo a la base de datos cuando está reservada para otros usuarios, pero no hay forma de probar mi argumento ni tengo ninguna solución.

¿Alguien ha tenido este tipo de problema antes? ¿Alguna sugerencia sobre cómo resolver este problema?

Muchas gracias por adelantado por su ayuda.

EDITAR: He consultado manualmente la base de datos utilizando la misma información recuperada del correo electrónico de error del servidor que recibí. Pude acceder a la entrada sin ningún problema. Además, parece que exactamente el mismo comportamiento que realizó el usuario no plantea ningún problema la mayor parte del tiempo, sino en algunos casos (que aún se desconocen). En conclusión, definitivamente no es un problema con la entrada que falta en la base de datos.

Chris P
fuente
2
Claramente, es un problema de datos: comment = Comment.objects.get(pk=comment_id)verifique que la identificación exista en la base de datos
karthikr
3
"python manage.py sqlall" generará el SQL correspondiente a sus modelos. Compruebe si corresponde al esquema de base de datos SQL. Si trabaja con PostgreSQL, por ejemplo, también puede ser un problema de secuencia. En conclusión: ¿puedes traer más información sobre tu entorno (SQDB, DB, tabla correspondiente en DB y código en models.py, ...)?
Ricola3D
@ Ricola3D Hola Ricola, Actualmente estoy usando MySql DB alojándolo desde la instancia Amazon EC2. Y estoy usando el comentario de Django incorporado por el momento. Mientras tanto, intentaré ejecutar el comando sqlall que sugirió. Gracias.
Chris P

Respuestas:

97

su línea que genera el error está aquí:

comment = Comment.objects.get(pk=comment_id)

intenta acceder a un comentario que no existe.

from django.shortcuts import get_object_or_404

comment = get_object_or_404(Comment, pk=comment_id)

En lugar de tener un error en su servidor, su usuario obtendrá un 404, lo que significa que intenta acceder a un recurso que no existe.

Ok hasta aquí, supongo que estás al tanto de esto.

Algunos usuarios (y yo soy parte de ellos) dejan que las pestañas se ejecuten durante mucho tiempo, si los usuarios están autorizados a eliminar datos, puede suceder. Un error 404 puede ser un error mejor para manejar un error de recurso eliminado que enviar un correo electrónico al administrador.

Otros usuarios van a direcciones de su historial (lo mismo si se han eliminado datos, ya que puede suceder).

christophe31
fuente
3
+1 en pestañas de larga duración. 404 a través de pestañas antiguas me pasa mucho.
Yuji 'Tomita' Tomita
Gracias Chris por tu sugerencia. Lo que realmente me molesta es que cuando consulto la base de datos MySql manualmente (usando la información de error que recibí del servidor), acierto la entrada correcta sin ningún problema. Además, la misma acción a veces arroja la excepción DoesNotExist, pero funciona la mayoría de las otras veces. No parece ser el problema con la entrada que falta en la base de datos :(
Chris P
Puede que tenga menos usuarios, pero con postgres nunca tuve este tipo de problemas. Realmente no tenemos mucha información, ¿su base de datos no tiene agrupación esclava / maestra? ¿No usa caché en conjuntos de consultas?
christophe31
@ christophe31 Así que todavía no he implementado ningún tipo de optimización del rendimiento de la base de datos ni métodos de copia de seguridad como el agrupamiento esclavo / maestro o el almacenamiento en caché en conjuntos de consultas. Supongo que implementaré esas funciones y veré si el problema persiste.
Chris P
2
También es posible añadir esto en la trampa: from django.db import connection, connection.connection.close(), connection.connection = Nonepara tratar de restablecer la conexión db y empezar de una nueva.
christophe31
106

Tal vez no tenga un registro de Comentarios con dicha clave primaria, entonces debería usar este código:

try:
    comment = Comment.objects.get(pk=comment_id)
except Comment.DoesNotExist:
    comment = None
Dracontis
fuente
3
La mejor opción en tales casos. En lugar de lanzar 404 al usuario, detecta el error y muestra un bonito mensaje preconfigurado. No arde el corazón.
user12379095
¿Cómo funcionaría aquí? def previous_job(self): return self.get_previous_by_start_dt(brand=self.brand, status='finished') or Noneno sé cómo implementar la captura de prueba aquí
snh_nl
22

Puedes usar esto:

comment = Comment.objects.filter(pk=comment_id)
Klang Wutcharin
fuente
Bueno, si hay un objeto específico que desea, entonces no puede usar el filtro ya que puede devolver una lista vacía si la consulta no coincide. Y cuando coincidió, entonces debes usar el primer objeto de la lista.
Jay Modi
3
Presumiblemente, ese es el punto: usar el filtro y probar si el resultado tiene cero o una entrada, en lugar de generar una excepción
Mike 'Pomax' Kamermans
Vale la pena señalar que Model.objects.filterdevolverá un Queryset, mientras Model.objects.getque devolverá un objeto. Si el objeto no existe, el primero devolverá un conjunto de consultas vacío, el segundo dará como resultado un Model.DoesNotExisterror.
ron_g
Comment.objects.filter(pk=comment_id).first()volverá Nonesi no se encuentran registros.
steezeburger
12

Puede intentarlo de esta manera. solo usa una función para obtener tu objeto

def get_object(self, id):
    try:
        return Comment.objects.get(pk=id)
    except Comment.DoesNotExist:
        return False
Mehedi Hasan
fuente