Метод prefetch_related

Метод prefetch_related применяется к QuerySet и позволяет заранее загрузить связанные объекты для уменьшения количества запросов к базе данных. В отличие от select_related, который использует JOIN, prefetch_related выполняет отдельные запросы для каждой связи и объединяет результаты на стороне Python. Метод поддерживает связи многие-ко-многим, обратные связи и вложенные отношения через использование специального класса Prefetch.

Синтаксис

pythonModel.objects.prefetch_related(*lookups)

Параметры:

Пример . С обычной связью

Рассмотрим модель блога с авторами и категориями:

pythonfrom django.db import models

class Author(models.Model):
  name = models.CharField(max_length=100)
  email = models.EmailField()

class Category(models.Model):
  name = models.CharField(max_length=50)

class Article(models.Model):
  title = models.CharField(max_length=200)
  content = models.TextField()
  created_at = models.DateTimeField(auto_now_add=True)
  author = models.ForeignKey(Author, on_delete=models.CASCADE)
  categories = models.ManyToManyField(Category)

Давайте загрузим статьи вместе с их авторами и категориями:

pythonfrom myapp.models import Article

# Загружаем статьи с авторами и категориями
articles = Article.objects.prefetch_related('author', 'categories')

for article in articles:
  print(f"Article: {article.title}")
  print(f"Author: {article.author.name}")
  categories = [cat.name for cat in article.categories.all()]
  print(f"Categories: {', '.join(categories)}")

Результат выполнения кода:

python"Article: Django Best Practices"
"Author: John Doe"
"Categories: Web, Backend, Python"
"Article: Database Optimization"
"Author: Jane Smith"
"Categories: Database, Performance"

Пример . С вложенными связями

Давайте загрузим комментарии к статьям с информацией об авторах комментариев:

pythonfrom myapp.models import Article

# Загружаем статьи с комментариями и авторами комментариев
articles = Article.objects.prefetch_related(
  'comments__author'
)

for article in articles:
  print(f"Article: {article.title}")
  for comment in article.comments.all():
    print(f"  Comment by {comment.author.name}: {comment.text}")

Пример . С использованием Prefetch

Используем класс Prefetch для более тонкой настройки загрузки:

pythonfrom django.db.models import Prefetch
from myapp.models import Article, Category

# Загружаем статьи с фильтрацией категорий
categories = Category.objects.filter(name__icontains='web')
articles = Article.objects.prefetch_related(
  Prefetch('categories', queryset=categories, to_attr='web_categories')
)

for article in articles:
  print(f"Article: {article.title}")
  for category in article.web_categories:
    print(f"  Web category: {category.name}")

Результат выполнения кода:

python"Article: Django Best Practices"
"  Web category: Web"
"  Web category: Backend"
"Article: Modern Frontend"
"  Web category: Web"
"  Web category: CSS"

Смотрите также

  • метод select_related,
    который использует JOIN для загрузки связанных объектов в одном запросе
  • метод prefetch_related_objects,
    который позволяет применить prefetch к уже существующему списку объектов
  • класс Prefetch,
    который предоставляет расширенные возможности для настройки prefetch
  • класс to_attr,
    который позволяет сохранить результаты prefetch в отдельный атрибут объекта