РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
⊗pydjPmMRPR 152 of 187 menu

Предзагрузка связей prefetch_related в Django

Метод select_related хорошо работает, когда у записи одна связанная запись: категория у поста, миниатюра у поста. Но он не подходит для обратной стороны ForeignKey и для ManyToManyField: там связанных записей может быть много.

Для таких случаев есть prefetch_related. Он делает отдельный запрос за связанными объектами и затем склеивает их в Python.

Пусть у нас снова категории и посты:

categories

  • id
  • name

posts

  • id
  • title
  • category_id

Без оптимизации получение постов для каждой категории снова дает проблему N+1:

from main.models import Category categories = Category.objects.all() for category in categories: print(category.name) for post in category.posts.all(): print(' -', post.title)

Давайте подгрузим посты заранее через prefetch_related. В скобках передают имя обратной связи (здесь posts из related_name):

categories = Category.objects.prefetch_related('posts') for category in categories: print(category.name) for post in category.posts.all(): print(' -', post.title)

Теперь Django сделает два запроса: один за категориями и один за всеми нужными постами. В цикле лишних запросов не будет.

То же работает для many-to-many. Пусть посты связаны с тегами:

posts

  • id
  • title

tags

  • id
  • name

Подгрузим теги заранее - передадим имя поля связи:

from main.models import Post posts = Post.objects.prefetch_related('tags') for post in posts: print(post.title) for tag in post.tags.all(): print(' -', tag.name)

Получите все страны вместе с городами через prefetch_related.

Получите всех студентов вместе с курсами через prefetch_related.

Расскажите, чем prefetch_related отличается от select_related и когда какой метод использовать.

Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить