Пройшов вже опубліковані відповіді. Просто подумав, що буде краще, якщо я додам відповідь на фактичному прикладі.
Скажімо, у вас є 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об'єкти лише один раз, що покращує продуктивність.