Пройшов вже опубліковані відповіді. Просто подумав, що буде краще, якщо я додам відповідь на фактичному прикладі.
Скажімо, у вас є 3 моделі 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)
Тут ви можете запитувати M2
модель та її відносні M1
об’єкти, використовуючи select_relation
поле та M3
об’єкти, що використовують prefetch_relation
поле.
Однак, як ми вже згадували M1
, відношення з M2
- це ForeignKey
, воно просто повертає лише 1 запис для будь-якого M2
об'єкта. Те ж саме стосується OneToOneField
і.
Але M3
відношення з M2
- це ManyToManyField
яке може повернути будь-яку кількість M1
об'єктів.
Розглянемо випадок, коли у вас є 2 M2
об’єкти m21
, у m22
яких однакові 5 асоційованих M3
об’єктів з ідентифікаторами 1,2,3,4,5
. Коли ви отримуєте пов’язані M3
об'єкти для кожного з цих M2
об'єктів, якщо ви використовуєте вибрані пов'язані, це буде працювати.
Кроки:
- Знайдіть
m21
об’єкт.
- Запитайте всі
M3
об’єкти, пов’язані з m21
об'єктом, чиїми ідентифікаторами є 1,2,3,4,5
.
- Повторіть те ж саме для
m22
об'єкта та всіх інших M2
об'єктів.
Так як ми маємо однакові 1,2,3,4,5
ідентифікатори для обох m21
, m22
об'єкти, якщо ми використовуємо select_related варіант, він буде запитувати БД двічі для одних і тих же ідентифікаторів , які вже були вилучені.
Замість цього, якщо ви використовуєте prefetch_related, коли ви намагаєтеся отримати M2
об’єкти, він записує всі ідентифікатори, які повернулися вашим об’єктам (Примітка: лише ідентифікатори) під час запитівM2
таблиці і як останній крок, Django збирається зробити запит до M3
таблиці із набором усіх ідентифікаторів, M2
які повернули ваші об’єкти. і приєднати їх до M2
об'єктів, що використовують Python замість бази даних.
Таким чином ви запитуєте всі M3
об'єкти лише один раз, що покращує продуктивність.