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.


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ć).


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

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)

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.