2010-06-13 7 views
27

Czasami potrzebuję upewnić się, że niektóre wystąpienia są wykluczone z zestawu zapytań.
ten sposób robię to zazwyczaj:Django z wyłączeniem określonych instancji z zestawu zapytań bez korzystania z wyszukiwania pola

unwanted_instance = MyModel.objects.get(pk=bad_luck_number) 
uninteresting_stuff_happens() 
my_results = MyModel.objects.exclude(id=unwanted_instance.id) 

lub, jeśli mam więcej z nich:

my_results = MyModel.objects.exclude(id_in=[uw_in1.id, uw_in2.id, uw_in3.id]) 

Ten 'czuje się' nieco niezgrabne, więc próbowałem:

my_ideally_obtained_results = MyModel.objects.exclude(unwanted_instance) 

Co nie działa. Ale przeczytałem here on SO, że podzapytanie może być używane jako parametr do wykluczenia.
Czy mam pecha? Czy brakuje mi jakiejś funkcjonalności (sprawdziłem dokumenty, ale nie znalazłem przydatnego wskaźnika)?

Odpowiedz

61

Sposób, w jaki już to robisz, jest najlepszym sposobem.

Jeśli jest to modelowo-agnostyczny sposób robienia tego, czego szukasz, nie zapomnij, że możesz zrobić query.exclude(pk=instance.pk).

Tak na marginesie, jeśli ORM Django miał mapowania tożsamości (którym nie w chwili obecnej), a następnie będzie można coś zrobić jak MyModel.objects.filter(<query>).all().remove(<instance>), ale masz pecha w tym względzie. Sposób, w jaki to robisz (lub ten powyżej) jest najlepszy, jaki masz.

Oh, a także można zrobić o wiele lepsze niż in zapytania z listowego: query.exclude(id__in=[o.id for o in <unwanted objects>])

+3

Ponadto, jeśli masz th e zestaw pytań do wykluczenia (np. 'MyModel.objects.filter ()'), możesz uzyskać identyfikatory używając 'ValuesQuerySet': tak: ' id_dicts = MyModel.objects.filter (). Values ​​('id ') 'a następnie ' query.exclude (id__in = [item [' id '] dla elementu w id_dicts]) '. –

+2

Prawie 4 lata później i ta odpowiedź rozwiązała mój problem. :-) – Garfonzo

+2

Chciałem tylko dodać coś do sugestii @ RacingTadpole: Możesz łatwo użyć 'values_list (" id ", flat = True)', aby uzyskać sekwencyjną listę wszystkich identyfikatorów. To jednak trafi w DB, więc proponuję użyć zrozumienia list Pythona. – stschindler

3

dana odpowiedź jest doskonały i spróbować tego, który działa dobrze dla mnie

etap 1)

from django.db.models import Q 

krok 2)

MyModel.objects.filter(~Q(id__in=[o.id for o in <unwanted objects>])) 
+9

W jaki sposób używa się wyrażenia 'Q' lepiej niż' .exclude (id__in = [o.id dla o in ]) '? – lanzz

+0

to jeszcze jedno alternatywne rozwiązanie, aby osiągnąć ten sam – kartheek

+0

To wydaje się bardzo nieskuteczną alternatywą. –

Powiązane problemy