Przejrzał już opublikowane odpowiedzi. Pomyślałem, że byłoby lepiej, jeśli dodam odpowiedź z faktycznym przykładem.
Powiedzmy, że masz 3 powiązane modele Django.
class M1(models.Model):
name = models.CharField(max_length=10)
class M2(models.Model):
name = models.CharField(max_length=10)
select_relation = models.ForeignKey(M1, on_delete=models.CASCADE)
prefetch_relation = models.ManyToManyField(to='M3')
class M3(models.Model):
name = models.CharField(max_length=10)
Tutaj możesz zapytać o M2model i jego względne M1obiekty za pomocą select_relationpola i M3obiektów za pomocą prefetch_relationpola.
Jednak, jak wspomnieliśmy M1, relacja z M2jest ForeignKey, to zwraca tylko 1 rekord dla dowolnego M2obiektu. To samo dotyczy OneToOneFieldrównież.
Ale M3relacja z M2jest tą, ManyToManyFieldktóra może zwrócić dowolną liczbę M1obiektów.
Rozważ przypadek, w którym masz 2 M2przedmioty m21, m22które mają takie same 5M3 obiektów powiązanych z identyfikatorami 1,2,3,4,5. Podczas pobierania powiązanych M3obiektów dla każdego z nichM2 obiektów, jeśli użyjesz opcji „Wybierz powiązane”, tak to będzie działać.
Kroki:
- Odnaleźć
m21 obiekt.
- Zapytaj wszystkie
M3obiekty związane zm21 obiektami, których identyfikatory to1,2,3,4,5 .
- Powtórz to samo dla
m22obiektu i wszystkich innychM2 obiektów.
Ponieważ mamy te same 1,2,3,4,5identyfikatory dla obum21 ,m22 obiektów, jeśli używamy opcji select_related, to będzie kwerendy DB dwukrotnie za te same identyfikatory, które były już naciągane.
Zamiast tego, jeśli użyjesz parametru prefetch_related, przy próbie uzyskania M2obiektów zanotuje wszystkie identyfikatory zwrócone przez Twoje obiekty (Uwaga: tylko identyfikatory) podczas zapytania do M2tabeli, a na ostatnim etapie Django wykona zapytanie do M3tabeli z zestawem wszystkich twoich identyfikatorówM2 zwróconych przez obiekty. i dołącz do nichM2 obiektów za pomocą Pythona zamiast bazy danych.
W ten sposób odpytujesz wszystkie M3obiekty tylko raz, co poprawia wydajność.