Błąd Django - pasujące zapytanie nie istnieje

92

W końcu wydałem swój projekt na poziom produkcyjny i nagle mam pewne problemy, z którymi nigdy nie miałem do czynienia w fazie rozwoju.

Kiedy użytkownicy publikują jakieś działania, czasami pojawia się następujący błąd.

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

To, co mnie naprawdę frustruje, to fakt, że projekt działa dobrze w środowisku lokalnym, a ponadto pasujący obiekt zapytania ISTNIEJE w bazie danych.

Teraz podejrzewam, że użytkownik uzyskuje dostęp do bazy danych, gdy jest ona zarezerwowana dla innych użytkowników, ale nie ma możliwości udowodnienia mojego argumentu ani nie mam na to żadnego rozwiązania.

Czy ktoś miał wcześniej tego typu problem? Jakieś sugestie, jak rozwiązać ten problem?

Z góry dziękuję za pomoc.

EDYCJA: ręcznie przeszukałem bazę danych, korzystając z tych samych informacji, które otrzymałem w wiadomości e-mail o błędzie serwera. Udało mi się trafić na wpis bez problemu. Ponadto wydaje się, że dokładnie to samo zachowanie, które wykonał użytkownik, przez większość czasu nie powoduje żadnego problemu, ale raczej w niektórych (jeszcze nieznanych) przypadkach. Podsumowując, na pewno nie jest to problem z brakującym wpisem w bazie danych.

Chris P
źródło
2
Najwyraźniej jest to problem z danymi: comment = Comment.objects.get(pk=comment_id)sprawdź, czy identyfikator istnieje w bazie danych
karthikr
3
„python manage.py sqlall” wygeneruje kod SQL odpowiadający Twoim modelom. Sprawdź, czy odpowiada SQL schematu bazy danych. Na przykład podczas pracy z PostgreSQL może to być również kwestia kolejności. Podsumowując: czy możesz przynieść więcej informacji o swoim środowisku (SQDB, DB, odpowiednia tabela w bazie danych i kod w models.py, ...)?
Ricola3D
@ Ricola3D Witaj Ricola, obecnie używam MySql DB, hostując ją z instancji Amazon EC2. I na razie korzystam z wbudowanego w Django Comment. W międzyczasie spróbuję uruchomić zasugerowane polecenie sqlall. Dziękuję Ci.
Chris P

Odpowiedzi:

97

Twoja linia podnosząca błąd jest tutaj:

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

próbujesz uzyskać dostęp do nieistniejącego komentarza.

from django.shortcuts import get_object_or_404

comment = get_object_or_404(Comment, pk=comment_id)

Zamiast mieć błąd na serwerze, użytkownik otrzyma 404, co oznacza, że ​​próbuje uzyskać dostęp do nieistniejącego zasobu.

Do tej pory ok, przypuszczam, że jesteś tego świadomy.

Niektórzy użytkownicy (a ja jestem ich częścią) pozwalają na działanie kart przez długi czas, jeśli użytkownicy mają uprawnienia do usuwania danych, może się tak zdarzyć. Błąd 404 może być lepszym błędem do obsługi błędu usuniętego zasobu niż wysłanie e-maila do administratora.

Inni użytkownicy przechodzą pod adresy ze swojej historii (tak samo, jeśli dane zostały usunięte, ponieważ może się to zdarzyć).

christophe31
źródło
3
+1 na długich kartach. 404 za pośrednictwem starych kart często mi się przytrafia.
Yuji 'Tomita' Tomita
Dziękuję Chris za sugestię. Naprawdę przeszkadza mi to, że kiedy ręcznie odpytuję bazę danych MySql (używając informacji o błędach, które otrzymałem z serwera), trafiam we właściwy wpis bez żadnego problemu. Ponadto ta sama akcja czasami zgłasza wyjątek DoesNotExist, ale działa w większości przypadków. Nie wygląda to na problem z brakującym wpisem w bazie danych :(
Chris P
Mogę mieć mniej użytkowników, ale z postgresami nigdy nie miałem tego rodzaju problemów. Naprawdę nie mamy wielu informacji, twoja baza danych nie ma klastrów slave / master? Nie używasz pamięci podręcznej w querysets?
christophe31
@ christophe31 Tak naprawdę nie zaimplementowałem jeszcze żadnego rodzaju optymalizacji wydajności bazy danych ani metod tworzenia kopii zapasowych, takich jak klastrowanie slave / master lub buforowanie na zestawach zapytań. Chyba zaimplementuję te funkcje i zobaczę, czy problem będzie się powtarzał.
Chris P
2
Również można dodać to na połów: from django.db import connection, connection.connection.close(), connection.connection = Noneaby spróbować przywrócić db połączenie i rozpocząć z nową.
christophe31
106

Może nie masz rekordu Komentarze z takim kluczem podstawowym, powinieneś użyć tego kodu:

try:
    comment = Comment.objects.get(pk=comment_id)
except Comment.DoesNotExist:
    comment = None
Dracontis
źródło
3
Najlepsza opcja w takich przypadkach. Zamiast rzucać 404 na użytkownika, złap błąd i wyświetl ładną, wstępnie skonfigurowaną wiadomość. Żadne serce nie pali.
user12379095
Jak by to tutaj działało? def previous_job(self): return self.get_previous_by_start_dt(brand=self.brand, status='finished') or Nonenie wiem, jak zaimplementować tutaj try catch
snh_nl
22

Możesz użyć tego:

comment = Comment.objects.filter(pk=comment_id)
Klang Wutcharin
źródło
Cóż, jeśli istnieje konkretny obiekt, który chcesz, nie możesz użyć filtru, ponieważ może zwrócić pustą listę, jeśli zapytanie nie pasuje. A kiedy to pasuje, musisz użyć pierwszego obiektu z listy.
Jay Modi
3
Przypuszczalnie o to chodzi: użyj filtru i sprawdź, czy wynik ma zero czy jeden wpis, zamiast generować wyjątek?
Mike 'Pomax' Kamermans
Warto zauważyć, że Model.objects.filterzwróci to Queryset, podczas gdy Model.objects.getzwróci obiekt. Jeśli obiekt nie istnieje, pierwszy zwróci pusty zestaw zapytań, drugi spowoduje Model.DoesNotExistbłąd.
ron_g
Comment.objects.filter(pk=comment_id).first()zwróci, Nonejeśli nie zostaną znalezione żadne rekordy.
steezeburger
12

Możesz spróbować w ten sposób. po prostu użyj funkcji, aby pobrać obiekt

def get_object(self, id):
    try:
        return Comment.objects.get(pk=id)
    except Comment.DoesNotExist:
        return False
Mehedi Hasan
źródło