2010-06-15 15 views
13

W Django można użyć wykluczenia do utworzenia SQL podobnego do not equal. Przykładem może być.Jak wykluczyć wyniki za pomocą get_object_or_404?

Model.objects.exclude(status='deleted') 

To działa świetnie, a wykluczenie jest bardzo elastyczne. Ponieważ jestem trochę leniwy, chciałbym, aby ta funkcjonalność podczas korzystania get_object_or_404, ale nie znaleźli sposób, aby to zrobić, ponieważ nie można wykluczyć na get_object_or_404 używać.

Co chcę to zrobić coś takiego:

model = get_object_or_404(pk=id, status__exclude='deleted') 

Ale niestety to nie działa, ponieważ nie jest wykluczenie filtr kwerendy lub podobny. Najlepszym Mam wymyślić do tej pory robi coś takiego:

object = get_object_or_404(pk=id) 
if object.status == 'deleted': 
    return HttpResponseNotfound('text') 

Robi coś takiego, naprawdę pokonuje punkt za pomocą get_object_or_404, ponieważ nie jest już przydatny jedno-liner.

Ewentualnie mogę zrobić:

object = get_object_or_404(pk=id, status__in=['list', 'of', 'items']) 

Ale to nie byłoby bardzo utrzymaniu, gdyż muszę zachować listę aktualne.

Zastanawiam się, czy brakuje mi jakiejś sztuczki lub funkcji w django, aby użyć get_object_or_404, aby uzyskać pożądany wynik?

+0

To nie jest odpowiedź, ale wygląda na to, że nie chcemy 404 dla miękkiego usuniętego obiektu. Celem delikatnego usuwania jest zatrzymanie obiektu "na wszelki wypadek". –

Odpowiedz

17

Zastosowanie django.db.models.Q:

from django.db.models import Q 

model = get_object_or_404(MyModel, ~Q(status='deleted'), pk=id) 

Obiekty Q pozwala NIE (z ~ operatora) i OR (z | operatora) oprócz I.

Zauważ, że obiekt Q musi przyjść przed pk=id, ponieważ argumenty słów kluczowych musi pochodzić ostatni w Pythonie.

+0

Przyczyna obiektu Q. Nie wiedziałem, że zadziała w tym konkursie. Thanx. – googletorp

+1

Oprócz modelu, jako pierwszy parametr można również przekazać menedżer lub zestaw kwerend. Zobacz http://stackoverflow.com/a/26476339/336694 – Heliodor

1

Jest inny sposób, zamiast używać przedmiotów q. Zamiast przekazując model get_object_or_404 prostu przekazać QuerySet do funkcji zamiast:

model = get_object_or_404(MyModel.objects.filter(pk=id).exclude(status='deleted'))

jednej strony efekt ten jest jednak to, że będzie podnieść MultipleObjectsReturned wyjątek jeśli QuerySet zwraca wiele wyników.

6

Najczęstszym przypadek użycia jest przeniesienie modelu. Jednak można również przejść instancję queryset:

queryset = Model.objects.exclude(status='deleted') 
get_object_or_404(queryset, pk=1) 

Django docs przykład: https://docs.djangoproject.com/en/1.10/topics/http/shortcuts/#id2

+0

Myślę, że jest to łatwiejsze do naśladowania rozwiązanie niż zaakceptowana odpowiedź. Mam na myśli to, że jeśli przeglądam mój kod sprzed 6 miesięcy, chciałbym uderzyć się w twarz, gdybym użył obiektu Q zamiast filtrowania z wykluczeniem. –

0

get_object_or_404 wykorzystuje metodę kierownika obiektu get_queryset. Jeśli przesłonisz metodę get_queryset, aby zwracać tylko te elementy, które nie zostały "usunięte", wtedy get_object_or_404 zachowa się automatycznie tak, jak chcesz. Zastąpienie tego problemu prawdopodobnie będzie jednak miało inne problemy (być może na stronach administratora), ale możesz dodać alternatywnego menedżera, gdy chcesz uzyskać dostęp do elementów usuniętych.

from django.db import models 

class ModelManger(models.Manger): 
    def get_queryset(self): 
     return super(ModelManger, self).get_queryset().exclude(status='deleted') 

class Model(models.Model): 
    # ... model properties here ... 

    objects = ModelManager() 
    all_objects = models.Manager() 

Więc jeśli potrzebujesz tylko nieusuniętych elementów można zrobić get_object_or_404(Models, id=id) ale jeśli trzeba wszystkie elementy, które można zrobić get_object_or_404(Models.all_objects, id=id).

Powiązane problemy