Метод select_related
Метод select_related применяется к QuerySet и возвращает новый QuerySet,
который выполняет SQL-запрос с JOIN для подгрузки связанных объектов.
Аргументы передаются в виде строк с именами полей отношений (ForeignKey, OneToOneField).
Это позволяет сократить количество запросов к базе данных при обращении к связанным данным.
Метод работает только с отношениями "один-к-одному" и "один-ко-многим" в прямом направлении.
При использовании select_related связанные объекты загружаются заранее,
что особенно полезно при итерации по большому количеству записей.
Синтаксис
Model.objects.select_related(*fields)
Пример
Рассмотрим модели Article и Author. У статьи есть автор, связанный через ForeignKey. Без select_related каждый доступ к автору вызывает отдельный запрос. Используем select_related для оптимизации:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
class Article(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
published_date = models.DateTimeField()
# Использование select_related
articles = Article.objects.select_related('author').all()
for article in articles:
print(article.author.name)
Результат выполнения кода:
"John Doe"
"Jane Smith"
"Bob Johnson"
Пример
select_related можно использовать с несколькими связанными полями. Например, если у статьи есть автор, а у автора - профиль:
from django.db import models
class Profile(models.Model):
bio = models.TextField()
author = models.OneToOneField(Author, on_delete=models.CASCADE)
# Загрузка автора и профиля
articles = Article.objects.select_related('author__profile').all()
for article in articles:
print(article.author.profile.bio)
Результат выполнения кода:
"Experienced writer"
"Tech enthusiast"
"Science fiction fan"
Пример
select_related часто комбинируется с filter для оптимизации конкретных выборок. Загружаем только опубликованные статьи с авторами:
from datetime import datetime
articles = (Article.objects
.select_related('author')
.filter(published_date__lte=datetime.now()))
res = [(a.title, a.author.name) for a in articles]
print(res)
Результат выполнения кода:
[("Django tutorial", "John Doe"), ("Python basics", "Jane Smith")]
Смотрите также
-
метод
prefetch_related,
который оптимизирует запросы для ManyToManyField -
метод
only,
который загружает только указанные поля -
метод
defer,
который исключает поля из выборки -
метод
select_for_update,
который блокирует записи для обновления