Метод select_related

Метод select_related применяется к QuerySet и возвращает новый QuerySet, который выполняет SQL-запрос с JOIN для подгрузки связанных объектов. Аргументы передаются в виде строк с именами полей отношений (ForeignKey, OneToOneField). Это позволяет сократить количество запросов к базе данных при обращении к связанным данным. Метод работает только с отношениями "один-к-одному" и "один-ко-многим" в прямом направлении. При использовании select_related связанные объекты загружаются заранее, что особенно полезно при итерации по большому количеству записей.

Синтаксис

pythonModel.objects.select_related(*fields)

Пример

Рассмотрим модели Article и Author. У статьи есть автор, связанный через ForeignKey. Без select_related каждый доступ к автору вызывает отдельный запрос. Используем select_related для оптимизации:

pythonfrom 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)

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

python"John Doe"
"Jane Smith"
"Bob Johnson"

Пример

select_related можно использовать с несколькими связанными полями. Например, если у статьи есть автор, а у автора - профиль:

pythonfrom 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)

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

python"Experienced writer"
"Tech enthusiast"
"Science fiction fan"

Пример

select_related часто комбинируется с filter для оптимизации конкретных выборок. Загружаем только опубликованные статьи с авторами:

pythonfrom 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)

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

python[("Django tutorial", "John Doe"), ("Python basics", "Jane Smith")]

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

  • метод prefetch_related,
    который оптимизирует запросы для ManyToManyField
  • метод only,
    который загружает только указанные поля
  • метод defer,
    который исключает поля из выборки
  • метод select_for_update,
    который блокирует записи для обновления