2015-10-14 42 views
6

Kiedy chcę zaznaczyć obiekty z funkcji get() jakJak obsługiwać „dopasowywania zapytania nie istnieje” podczas pobierania obiektu

personalProfile = World.objects.get(ID=personID) 

Jeśli dostać funkcji nie zwraca znaleźć wartość, jest " pasujące zapytanie nie istnieje. " występuje błąd.

Jeśli nie muszę tego błędu, użyję spróbować z wyjątkiem funkcji

try: 
    personalProfile = World.objects.get(ID=personID) 
except: 
    pass 

Ale myślę, że nie jest to najlepszy sposób, ponieważ używam

except: 
     pass 

Proszę polecić jakiś pomysł lub próbka kodu do walki z tym problemem

Odpowiedz

10

To zależy od tego, co chcesz zrobić, jeśli nie istnieje.

Theres get_object_or_404:

zwraca get() na danym modelu kierownika, ale to podnosi Http404 zamiast modelu DoesNotExist wyjątku.

get_object_or_404(World, ID=personID) 

która jest bardzo zbliżona do tej próbie z wyjątkiem kodu aktualnie robimy.

Inaczej tam get_or_create:

personalProfile, created = World.objects.get_or_create(ID=personID) 

Chociaż Jeśli zdecydujesz się kontynuować obecnego podejścia, przynajmniej upewnić się, że wyjątkiem jest zlokalizowana na prawidłowe błędu, a następnie zrobić coś z tym jako niezbędny

try: 
    personalProfile = World.objects.get(ID=personID) 
except MyModel.DoesNotExist: 
    raise Http404("No MyModel matches the given query.") 

powyższy try/z wyjątkiem uchwytu jest podobna do tego, co można znaleźć w docs dla get_object_or_404 ...

+1

Dzięki za pomoc. Próbuję tego i otrzymuję błąd , ponieważ nie importowałem Http404 . Napraw to przez "z django.http import Http404" i idealnie! –

2

Funkcja get_or_none() została teraz proposed, multipletimes teraz. Powiadomienie o odrzuceniu to funkcja pełzania, z którą możesz lub nie możesz się zgodzić. Funkcjonalność jest obecna - z nieco inną semantyką - w metodzie zapytań first().

Ale pierwsze rzeczy pierwsze:

Menedżer rzuca World.DoesNotExist, wyspecjalizowanym podklasa ObjectDoesNotExist gdy World obiekt nie został znaleziony:

try: 
    personalProfile = World.objects.get(ID=personID) 
except World.DoesNotExist: 
    pass 

Jest też get_object_or_404() który podnosi Http404 wyjątek, gdy obiekt był nie znaleziono.

Możesz także przetasować swój własny get_or_none(). Ewentualna realizacja może być:

def get_or_none(queryset, *args, **kwargs): 
    try: 
     return queryset.get(*args, **kwargs) 
    except ObjectDoesNotExist: 
     return None 

Należy pamiętać, że to wciąż budzi MultipleObjectsReturned, gdy więcej niż jeden obiekt zostanie znaleziony.Jeśli chcesz zawsze pierwszy obiekt niezależnie od wszelkich innych, można uprościć używając first(), która zwraca None gdy queryset jest pusty:

def get_or_none(queryset, *args, **kwargs): 
    return queryset.filter(*args, **kwargs).first() 

Uwaga jednak na to, aby pracować niezawodnie, trzeba odpowiedniej kolejności dla obiektów , ponieważ w obecności wielu obiektów first() może być niedeterministyczny (prawdopodobnie zwraca pierwszy obiekt z indeksu bazy danych używanego do filtrowania zapytania i ani indeksy, ani stoły bazowe nie muszą być sortowane, a nawet mieć powtarzalne zamówienie).

Używaj obu jednak tylko wtedy, gdy użycie obiektu do pobrania jest całkowicie opcjonalne dla dalszego przepływu programu. Gdy niepowodzenie w pobieraniu obiektu jest błędem, użyj get_object_or_404(). Jeśli obiekt ma zostać utworzony, gdy nie istnieje, użyj get_or_create(). W tych przypadkach obie są lepiej dostosowane do uproszczenia przepływu programu.

+3

Metoda ['first()'] (https://docs.djangoproject.com/en/1.8/ref/models/querysets/#first) dodana w Django 1.6 jest podobna do 'get_or_none'. Zauważ, że nie obsługujesz 'MultipleObjectsReturned' w twojej metodzie. Metoda 'first()' po prostu bierze pierwszy element i ignoruje resztę. – Alasdair

+0

@Alairdair Nie radzenie sobie z 'MultipleObjectsReturned' jest dość celowe. Jednak tak, 'get_or_none()' można uprościć, aby użyć 'first()'. Czy sprawdziłeś, jak to wpływa na generowane zapytania SQL? – dhke

+1

Chodzi mi o to, że chociaż bilety, z którymi się łączyłeś zostały zamknięte, ponieważ nie zostaną naprawione, funkcja została ostatecznie dodana, ale z inną nazwą. 'MyModel.objects.filter (** kwargs) .first()' robi to samo 'get_object_or_none (MyModel, ** kwargs)', chyba że naprawdę dbasz o 'MultipleObjectsReturned' (którego spodziewam się przez większość czasu, kiedy nie wiesz) t). Nie sprawdzałem kodu SQL, ale spodziewam się, że będzie to podobne, może z pewnymi różnicami z 'limitem'. – Alasdair