Jaki jest właściwy sposób sprawdzenia, czy obiekt istnieje w widoku django bez zwracania błędu 404?


93

Muszę sprawdzić, czy obiekt istnieje i zwrócić obiekt, a następnie na podstawie tego wykonać akcje. Jaki jest właściwy sposób, aby to zrobić bez zwracania kodu 404?

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

if listing:

Rasiel, czy mogę zasugerować rozważenie przyjęcia innej odpowiedzi? Wydaje się, że jest to właściwy sposób zrobienia tego i spotkało się z dużo większym uznaniem niż zaakceptowana odpowiedź.
— Azendale

1
Mogę to uznać, jednak istnieje zostało wprowadzone w Django 1.2, które zostało wydane 17 maja 2010 r. Jeśli zauważysz, że moje pytanie zostało przesłane w 09… to była wtedy poprawna odpowiedź. Jeśli Exists () jest teraz uważane za najlepszy sposób na zrobienie tego, myślę, że byłoby semantycznie poprawne wybranie drugiej odpowiedzi, prawda?
— Rasiel

Rasiel, to ma sens, że to była wtedy poprawna odpowiedź. Ale strony stackoverflow wydają się w równym stopniu polegać na tworzeniu zestawu dobrych / oficjalnych pytań z najlepszymi odpowiedziami, jak na znajdowaniu rozwiązań problemów ludzi. Stąd moja sugestia, aby wybrać odpowiedź, która jest obecnie „oficjalnie poprawna”.
— Azendale,

if listing:Powinno być else:.
— Chronial

Odpowiedzi:


117

Nie użyłbym opakowania 404, gdybyś nie otrzymał 404. To jest nadużycie intencji. Zamiast tego po prostu złap DoesNotExist.

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

+1: Tak, jest to lepsze rozwiązanie niż przyjęte, jeśli nie chcesz 404.
— Carl Meyer

tak, to wydaje się być lepszym rozwiązaniem
— Rasiel

3
To rozwiązanie działa lepiej niż exists()gdybyś musiał coś zrobić z obiektem.
— SaeX

2
Lubię dodawać values_list('id', flat=True). jeśli muszę tylko sprawdzić, czy istniejelisting = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
— erajuan

To, co wydaje mi się dziwne w tej składni, RealEstateListing.DoesNotExistto odwoływanie się do modelu, a nie do samego obiektu. Dlaczego tak nie jest RealEstateListing.objects.get(slug_url=slug).DoesNotExist?
— Maxim Vallee

200

Możesz też:

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

Czasami bardziej oczywiste jest użycie try: except:bloku, a innym razem jednolinijka exists()sprawia, że ​​kod wygląda jaśniej ... wszystko zależy od logiki aplikacji.



7
to jest lepszy sposób i powinien mieć odpowiedź
— Jharwood

3
Zakładam, że exists()to nie działa get(), prawda?
— Eduard Luca,

9
Zwróć uwagę, że to rozwiązanie jest ważne tylko wtedy, gdy nie zamierzasz używać danego obiektu. W przeciwnym razie (jak w przypadku OP) jest źle i dużo wolniej niż przyjęte rozwiązanie: jeśli zrobisz to get()później, wyśle ​​drugie zapytanie do bazy danych.
— Chronial

1
Jeśli sprawdzanie istnienia zrobić coś z obiektu (jeśli istnieje), wtedy wolę try-exceptponad exists().
— Jithin Pavithran

7
listing = RealEstateListing.objects.filter(slug_url=slug).first() 

2
Jest to najlepsze rozwiązanie, jeśli musisz później użyć potencjalnego obiektu, ponieważ wymaga on tylko jednego przypisania i pozwala uniknąć używania bloku try / except. Zauważ, że możesz później przetestować istnienie po prostuif listing:
— Michael Hays,

Unikanie prób / z wyjątkiem jest złą praktyką. Jednym z najważniejszych aspektów rozwoju oprogramowania jest możliwość kontrolowania wyjątków, aby zapewnić dobre wrażenia użytkownika. Poinformuj innych, gdy coś nie działa prawidłowo. Druga; jeśli chcesz sprawdzić istnienie QuerySet, użyj .exists (), w przeciwnym razie jest obiektem. Sprawdź, czy istnieje klucz podstawowy ... if object.pk: // run code () To zapytanie jest znacznie szybsze niż pobieranie wszystkich danych obiektu. Chcesz tylko wiedzieć, czy istnieje.
— Wolfgang Leon,

2
Było już rozwiązanie wykorzystujące try / except i .exists(). Myślę, że dobrym pomysłem w SO jest posiadanie wielu różnych odpowiedzi, jak robić różne rzeczy. Może to jest lepsze dla tych, którzy również chcą użyć obiektu, jeśli istnieje. Nie ustalałbym żadnych zasad, jeśli należy unikać prób / wyjątków, czy nie. Czasami jest to dobre, a czasami złe, na przykład, jeśli chcesz stworzyć bardzo kompaktowy kod.
— Henrik Heino,

0

Zrobiłbym to w następujący sposób:

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

Nie widzę potrzeby próbowania / łapania. Jeśli w wyniku jest potencjalnie kilka obiektów, użyj metody first (), jak pokazuje użytkownik Henrik Heino


O ile nie wykonasz .first () na zestawie zapytań lub .first () w warunku, zawsze zwróci to True.
— B.Adler
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.