Как в Django ORM сделать несколько join к одной и той же таблице?

В Django ORM можно осуществить несколько join к одной и той же таблице с помощью использования методов prefetch_related или select_related. Оба метода позволяют оптимизировать запросы к БД и избежать N+1 проблемы, когда выполняется N запросов к БД для получения N связанных объектов.

Метод prefetch_related используется для получения связанных объектов (обратных связей) и выполняет отдельный запрос к БД для каждой связи. Он загружает все связанные объекты и создает кэш, что позволяет избежать дополнительных запросов при обращении к ним. Пример использования:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

# Загружаем связанные объекты Book с автором при запросе к БД
books = Book.objects.all().prefetch_related('author')

# Можно выполнить несколько join к таблице Author
# и получить все книги вместе с информацией об авторах
for book in books:
    print(book.title, book.author.name)

Метод select_related используется для получения связанных объектов (обратных связей) с помощью одного запроса INNER JOIN. Это позволяет избежать дополнительных запросов к БД и существенно повысить производительность. Пример использования:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

# Загружаем связанный объект Author с каждой книгой при запросе к БД
books = Book.objects.all().select_related('author')

# Получаем все книги вместе с информацией об авторах
for book in books:
    print(book.title, book.author.name)

Оба метода могут быть использованы вместе, чтобы выполнить несколько join к одной и той же таблице или к нескольким связям.