Spójrzmy na przykład z django docs z modelami Pizza and Topping. Jedna pizza może mieć wiele dodatków.Django Prefetch z niestandardowym zestawem zapytań, który korzysta z metody menedżerów
Jeśli robimy zapytanie:
pizzas = Pizza.objects.prefetch_related('toppings')
Będziemy uzyskać wszystkie pizze i ich dodatków w 2 zapytaniami. Teraz załóżmy, że chcę wstępne pobieranie tylko wegetariańskie polewy (zakładamy, mamy taką właściwość):
pizzas = Pizza.objects.prefetch_related(
Prefetch('toppings', queryset=Topping.objects.filter(is_vegetarian=True))
)
To działa całkiem dobrze i Django nie wykonuje kolejną kwerendę dla każdej pizzy, gdy zrobienie czegoś takiego:
for pizza in pizzas:
print(pizza.toppings.filter(is_vegetarian=True))
teraz załóżmy mamy menedżera niestandardową Doładowanie model i zdecydowaliśmy się umieścić tam metodę, która pozwala nam na filtrowanie tylko wegetariańskie siarkowe jak w przykładzie powyżej kod:
class ToppingManager(models.Manager):
def filter_vegetarian(self):
return self.filter(is_vegetarian=True)
Teraz robię nowe zapytanie i preselekcji niestandardowego queryset z mojej metody z menedżerem:
pizzas = Pizza.objects.prefetch_related(
Prefetch('toppings', queryset=Topping.objects.filter_vegetarian()))
a próbuję wykonać mój kod:
for pizza in pizzas:
print(pizza.toppings.filter_vegeterian())
dostaję nową kwerendę dla każdej iteracji pętli. Oto moje pytanie. Czemu? Obie te konstrukcje wrócić tego samego obiektu typu, który jest queryset:
Topping.objects.filter_vegetarian()
Topping.objects.filter(is_vegetarian=True)
Jeśli wykonujesz wstępne pobieranie za pomocą metody menedżera, ale następnie w pętli for do drukowania (pizza.toppings.filter (is_vegetarian = True)), czy robi dodatkowe kwerendy? Mam przeczucie, że rozumiem, dlaczego tak się dzieje, chcę tylko upewnić się, że działa tak, jak sobie wyobrażam. –
Zacząłem debugować i wygląda na to, że nawet w pierwszym przykładzie będziemy mieli również mnóstwo pytań. Dlatego docs polecają nas używać to_attr –
Ale nadal jest to interesujące. Dlaczego nie wdrożyć tej funkcji w django? Jeśli zestaw zapytań jest taki sam jak filtrowany po tym, jak nadal możemy używać wyników z pamięci podręcznej –