Это имеет аналогичную цель для select_related В том, что оба предназначены для остановки запросов базы данных, вызванные доступом к связанным объектам, но стратегия совсем другая.
select_related Работает, создавая присоединение SQL и включение полей связанного объекта в выборе оператора. По этой причине select_related Получает связанные объекты в той же базе данных. Однако, чтобы избежать гораздо более крупного набора результатов, который приведет к объединению через «много» отношений, select_related ограничен однозначными отношениями – иностранным ключом и однозначным.
Prefetch_related С другой стороны, делает отдельный поиск для каждой связи и делает «присоединение» в Python. Это позволяет ему предпринимать многие-много-много и много к одному объектам, которые не могут быть выполнены с использованием select_related.
Пойдем на нашу любимую часть примеров:
В этом у нас есть таблицы пользователей и языков, каждый пользователь знает более одного языка, и мы хотим перечислять пользователей с их языками
# models.py class Language(models.Model): name = models.CharField(max_length=63) code = models.CharField(max_length=7) class User(models.Model): fullname = models.CharField(max_length=127) languages = models.ManyToManyField(Language, related_name="users")
# serializers.py class LanguageSerializer(serializers.ModelSerializer): class Meta: model = Language fields = ('id', 'name', 'code') class UserSerializer(serializers.ModelSerializer): languages = LanguageSerializer(many=True) class Meta: model = User fields = ('id', 'fullname', 'languages')
# views.py class UserListView(ListAPIView): serializer_class = UserSerializer queryset = User.objects.prefetch_related('languages')
Согласно Prefetch_related Документация:
Чтобы избежать гораздо более крупного набора результатов, который приведет к объединению на «много» отношений, Prefetch_related делает отдельный поиск для каждой связи и делает «присоединение» в Python
Так что запрос User.objects.prefetch_related («Языки»)
будет разделен на 2 запроса:
SELECT "user"."id", "user"."fullname" FROM "user"
SELECT "user_language"."user_id","language"."id", "language"."name", "language"."code" FROM "language" INNER JOIN "user_language" ON ("language"."id" = "user_language"."language_id") WHERE "user_language"."user_id" IN (...);
И последнее, что соответствует этим запросам с Python
код
Оригинал: “https://dev.to/shawara/django-orm-optimization-tips-2-prefetchrelated-57oj”