Erro do Django - consulta correspondente não existe

98

Finalmente lancei meu projeto para o nível de produção e de repente tenho alguns problemas que nunca tive que lidar na fase de desenvolvimento.

Quando os usuários postam algumas ações, às vezes recebo o seguinte erro.

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

O que realmente me frustra é que o projeto funciona bem no ambiente local e, além disso, o objeto de consulta correspondente EXISTE no Banco de Dados.

Agora estou suspeitando que o usuário está acessando o Banco de Dados quando ele está reservado para outros usuários, mas não tenho como provar meu argumento nem tenho solução para ele.

Alguém já teve esse tipo de problema antes? Alguma sugestão sobre como resolver este problema?

Muito obrigado pela sua ajuda com antecedência.

EDIT: Eu consultei manualmente o banco de dados usando as mesmas informações recuperadas do e-mail de erro do servidor que recebi. Consegui acertar a entrada sem nenhum problema. Além disso, parece que o mesmo comportamento que o usuário realizou não levanta nenhum problema na maioria das vezes, mas em alguns casos (ainda desconhecidos). Em conclusão, definitivamente não é um problema com a entrada ausente no banco de dados.

Chris P
fonte
2
Claramente, é um problema de dados: comment = Comment.objects.get(pk=comment_id)verifique se a id existe no banco de dados
karthikr
3
"python manage.py sqlall" irá gerar o SQL correspondente aos seus modelos. Verifique se corresponde ao esquema SQL do banco de dados. Se estiver trabalhando com PostgreSQL, por exemplo, também pode ser um problema de sequência. Concluindo: você pode trazer mais informações sobre seu ambiente (SQDB, DB, tabela correspondente em DB e código em models.py, ...)?
Ricola3D
@ Ricola3D Olá Ricola, Atualmente estou usando MySql DB hospedando-o da instância do Amazon EC2. E estou usando o Django Comment embutido por enquanto. Enquanto isso, tentarei executar o comando sqlall que você sugeriu. Obrigado.
Chris P

Respostas:

105

sua linha levantando o erro está aqui:

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

você tenta acessar um comentário não existente.

from django.shortcuts import get_object_or_404

comment = get_object_or_404(Comment, pk=comment_id)

Em vez de ocorrer um erro no servidor, o usuário receberá um erro 404, o que significa que ele tenta acessar um recurso inexistente.

Ok, até aqui suponho que você esteja ciente disso.

Alguns usuários (e eu faço parte deles) deixam as abas rodarem por muito tempo, se os usuários estiverem autorizados a deletar dados, isso pode acontecer. Um erro 404 pode ser um erro melhor para lidar com um erro de recurso excluído do que enviar um e-mail para o administrador.

Outros usuários vão para endereços de seu histórico, (mesmo se os dados foram excluídos porque isso pode acontecer).

christophe31
fonte
3
+1 em guias de longa duração. 404 via abas antigas acontece muito comigo.
Yuji 'Tomita' Tomita
Obrigado Chris por sua sugestão. O que realmente me incomoda é que quando eu consulto o banco de dados MySql manualmente (usando as informações de erro que recebi do servidor) eu acerto a entrada correta sem nenhum problema. Além disso, a mesma ação às vezes lança a exceção DoesNotExist, mas funciona na maioria das outras vezes. Não parece ser o problema com a entrada ausente no banco de dados :(
Chris P
Posso ter menos usuários, mas com o postgres nunca tive esse tipo de problema. Realmente não temos muitas informações, seu banco de dados não possui cluster master / slave? Você não usa cache em querysets?
christophe31
@ christophe31 Portanto, ainda não implementei nenhum tipo de otimização de desempenho de banco de dados nem métodos de backup, como clustering mestre / escravo ou armazenamento em cache em querysets. Acho que vou implementar esses recursos e ver se o problema persiste.
Chris P
2
Além disso, você pode adicionar este na captura: from django.db import connection, connection.connection.close(), connection.connection = Nonepara tentar repor db conexão e iniciar a partir de um novo.
christophe31
112

Talvez você não tenha nenhum registro de comentários com essa chave primária, então você deve usar este código:

try:
    comment = Comment.objects.get(pk=comment_id)
except Comment.DoesNotExist:
    comment = None
Dracontis
fonte
3
A melhor opção em tais casos. Em vez de enviar 404 para o usuário, detecte o erro e exiba uma bela mensagem pré-configurada. Sem queimaduras cardíacas.
usuário12379095
Como isso funcionaria aqui? def previous_job(self): return self.get_previous_by_start_dt(brand=self.brand, status='finished') or Nonenão sei como implementar o try catch aqui
snh_nl
26

Você pode usar isto:

comment = Comment.objects.filter(pk=comment_id)
Klang Wutcharin
fonte
Bem, se houver um objeto específico que você deseja, você não pode usar o filtro, pois ele pode retornar uma lista vazia se a consulta não corresponder. E quando combinou, você deve usar o primeiro objeto da lista.
Jay Modi
3
Presumivelmente, esse é o ponto: usar o filtro e testar se o resultado tem zero ou uma entrada, em vez de gerar uma exceção?
Mike 'Pomax' Kamermans,
Vale ressaltar que Model.objects.filterretornará um Queryset, enquanto Model.objects.getque retornará um objeto. Se o objeto não existir, o primeiro retornará um queryset vazio, o último resultará em um Model.DoesNotExisterro.
ron_g
Comment.objects.filter(pk=comment_id).first()retornará Nonese nenhum registro for encontrado.
steezeburger
15

Você pode tentar desta forma. apenas use uma função para obter seu objeto

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