Функция prefetch_related_objects
Функция prefetch_related_objects применяется к существующему списку
моделей и выполняет превентивную подгрузку связанных объектов
для каждого элемента списка. Это позволяет избежать проблемы
"N+1 запросов", когда для каждого объекта выполняется отдельный
запрос для получения связанных данных. Функция принимает список
моделей и аргументы для указания связей, которые необходимо
предзагрузить.
Синтаксис
from django.db.models import prefetch_related_objects
prefetch_related_objects(objects, *lookups)
Параметры функции:
objects - итерируемый объект с моделями (QuerySet или список),
для которых нужно предзагрузить связанные данные.
*lookups - один или несколько аргументов, определяющих связи
для превентивной загрузки. Это могут быть строки с именами полей
связи или объекты Prefetch для более тонкой настройки.
Пример
Пусть у нас есть модели для статей и их авторов. Получим все статьи и подгрузим связанных авторов для каждой статьи:
from django.db import models
from django.db.models import prefetch_related_objects
class Author(models.Model):
name = models.CharField(max_length=100)
class Article(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
# Получаем все статьи
articles = list(Article.objects.all())
# Предзагружаем авторов для всех статей
prefetch_related_objects(articles, 'author')
for article in articles:
print(f"Article: {article.title}, Author: {article.author.name}")
Результат выполнения кода:
"Article: Django basics, Author: John Doe"
"Article: Advanced ORM, Author: Jane Smith"
"Article: Web development, Author: John Doe"
Пример
Рассмотрим более сложный случай с несколькими связями. Подгрузим авторов и их профили для списка статей:
from django.db import models
from django.db.models import prefetch_related_objects
class Profile(models.Model):
bio = models.TextField()
author = models.OneToOneField(Author, on_delete=models.CASCADE)
class Article(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
tags = models.ManyToManyField('Tag')
class Tag(models.Model):
name = models.CharField(max_length=50)
# Получаем недавние статьи
articles = list(Article.objects.filter(title__icontains='django'))
# Предзагружаем авторов и профили авторов
prefetch_related_objects(articles, 'author__profile')
for article in articles:
print(f"Article: {article.title}")
print(f"Author: {article.author.name}")
print(f"Bio: {article.author.profile.bio}")
print("---")
Результат выполнения кода:
"Article: Django basics"
"Author: John Doe"
"Bio: Senior developer with 10 years of experience"
"---"
"Article: Django advanced"
"Author: Jane Smith"
"Bio: Python expert and Django core contributor"
"---"
Пример
Использование функции с объектом Prefetch для дополнительной
фильтрации и сортировки подгружаемых данных:
from django.db import models
from django.db.models import prefetch_related_objects, Prefetch, Q
class Comment(models.Model):
text = models.TextField()
article = models.ForeignKey(Article, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
is_approved = models.BooleanField(default=True)
# Получаем статьи
articles = list(Article.objects.all())
# Создаем Prefetch объект для подгрузки только одобренных комментариев
prefetch_comments = Prefetch(
'comment_set',
queryset=Comment.objects.filter(is_approved=True).order_by('-created_at'),
to_attr='approved_comments'
)
# Применяем превентивную загрузку
prefetch_related_objects(articles, prefetch_comments)
for article in articles:
print(f"Article: {article.title}")
print(f"Comments count: {len(article.approved_comments)}")
for comment in article.approved_comments[:3]:
print(f" - {comment.text}")
print("---")
Результат выполнения кода:
"Article: Django basics"
"Comments count: 5"
" - Great article!"
" - Very helpful, thanks!"
" - Could you explain more about models?"
"---"
"Article: Advanced ORM"
"Comments count: 3"
" - This is exactly what I needed"
" - Excellent explanation"
" - Helped me optimize my queries"
"---"
Смотрите также
-
метод
prefetch_related,
который выполняет превентивную подгрузку связанных данных вQuerySet -
метод
select_related,
который выполняет превентивную подгрузку данных через JOIN в SQL -
класс
Prefetch,
который позволяет тонко настраивать превентивную загрузку данных -
метод
only,
который ограничивает загружаемые поля модели для оптимизации запросов