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 M2
model i jego względne M1
obiekty za pomocą select_relation
pola i M3
obiektów za pomocą prefetch_relation
pola.
Jednak, jak wspomnieliśmy M1
, relacja z M2
jest ForeignKey
, to zwraca tylko 1 rekord dla dowolnego M2
obiektu. To samo dotyczy OneToOneField
również.
Ale M3
relacja z M2
jest tą, ManyToManyField
która może zwrócić dowolną liczbę M1
obiektów.
Rozważ przypadek, w którym masz 2 M2
przedmioty m21
, m22
które mają takie same 5M3
obiektów powiązanych z identyfikatorami 1,2,3,4,5
. Podczas pobierania powiązanych M3
obiektó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
M3
obiekty związane zm21
obiektami, których identyfikatory to1,2,3,4,5
.
- Powtórz to samo dla
m22
obiektu i wszystkich innychM2
obiektów.
Ponieważ mamy te same 1,2,3,4,5
identyfikatory 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 M2
obiektów zanotuje wszystkie identyfikatory zwrócone przez Twoje obiekty (Uwaga: tylko identyfikatory) podczas zapytania do M2
tabeli, a na ostatnim etapie Django wykona zapytanie do M3
tabeli 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 M3
obiekty tylko raz, co poprawia wydajność.