Метод prefetch_related
Метод prefetch_related применяется к QuerySet и позволяет заранее загрузить связанные объекты для уменьшения количества запросов к базе данных. В отличие от select_related, который использует JOIN, prefetch_related выполняет отдельные запросы для каждой связи и объединяет результаты на стороне Python. Метод поддерживает связи многие-ко-многим, обратные связи и вложенные отношения через использование специального класса Prefetch.
Синтаксис
Model.objects.prefetch_related(*lookups)
Параметры:
lookups- строковые имена связанных полей, классыPrefetchили выражения для загрузки связанных объектов
Пример . С обычной связью
Рассмотрим модель блога с авторами и категориями:
from 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)
Давайте загрузим статьи вместе с их авторами и категориями:
from 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)}")
Результат выполнения кода:
"Article: Django Best Practices"
"Author: John Doe"
"Categories: Web, Backend, Python"
"Article: Database Optimization"
"Author: Jane Smith"
"Categories: Database, Performance"
Пример . С вложенными связями
Давайте загрузим комментарии к статьям с информацией об авторах комментариев:
from 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 для более тонкой настройки загрузки:
from 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}")
Результат выполнения кода:
"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 в отдельный атрибут объекта