Класс Prefetch
Класс Prefetch применяется совместно с методом prefetch_related для расширенной настройки предварительной загрузки связанных объектов. В отличие от обычного использования prefetch_related с строковыми аргументами, Prefetch позволяет передавать собственный QuerySet для загрузки связанных данных с дополнительными условиями фильтрации, сортировки и ограничениями. Он принимает три основных параметра: lookup (имя связи), queryset (настроенный QuerySet) и to_attr (опциональное имя атрибута для сохранения результатов). Класс особенно полезен когда нужно получить не все связанные объекты, а только их часть, удовлетворяющую определенным критериям.
Синтаксис
from django.db.models import Prefetch
Prefetch(lookup, queryset=None, to_attr=None)
Пример
Давайте предварительно загрузим только опубликованные статьи для каждого автора:
from myapp.models import Author, Article
from django.db.models import Prefetch
# Настраиваем QuerySet для статей с фильтрацией
published_articles = Article.objects.filter(status="published")
# Используем Prefetch для загрузки только опубликованных статей
authors = Author.objects.prefetch_related(
Prefetch("articles", queryset=published_articles)
)
for author in authors:
print(f"{author.name}: {author.articles.count()} published articles")
Результат выполнения кода:
"John Doe: 3 published articles"
"Jane Smith: 2 published articles"
"Bob Johnson: 0 published articles"
Пример
Теперь используем параметр to_attr для сохранения предварительно загруженных объектов в отдельный атрибут:
from myapp.models import Author, Article
from django.db.models import Prefetch
# Получаем последние 3 статьи для каждого автора
recent_articles = Article.objects.order_by("-created_at")[:3]
authors = Author.objects.prefetch_related(
Prefetch(
"articles",
queryset=recent_articles,
to_attr="recent_articles"
)
)
for author in authors:
for article in author.recent_articles:
print(f"{author.name}: {article.title}")
Результат выполнения кода:
"John Doe: Advanced Django"
"John Doe: Python Basics"
"Jane Smith: Web Development"
"Bob Johnson: Database Design"
Пример
Пример с цепочкой Prefetch для вложенных связей и комбинированной фильтрации:
from myapp.models import Author, Article, Comment
from django.db.models import Prefetch
# Настраиваем Prefetch для комментариев к статьям
recent_comments = Comment.objects.order_by("-created_at")[:5]
# Настраиваем Prefetch для статей с комментариями
articles_with_comments = Article.objects.prefetch_related(
Prefetch("comments", queryset=recent_comments, to_attr="recent_comments")
)
# Основной запрос с вложенным Prefetch
authors = Author.objects.prefetch_related(
Prefetch("articles", queryset=articles_with_comments)
)
for author in authors:
for article in author.articles.all():
print(f"{author.name} - {article.title}: {len(article.recent_comments)} comments")
Результат выполнения кода:
"John Doe - Advanced Django: 3 comments"
"John Doe - Python Basics: 2 comments"
"Jane Smith - Web Development: 1 comment"
"Bob Johnson - Database Design: 0 comments"
Смотрите также
-
метод
prefetch_related,
который выполняет предварительную загрузку связанных объектов -
метод
select_related,
который выполняет загрузку связанных объектов через JOIN -
метод
filter,
который фильтруетQuerySetпо заданным условиям -
метод
order_by,
который сортируетQuerySetпо указанным полям