JavaRush /Курсы /Модуль 3: Django /Работа с related_name и related_query_name

Работа с related_name и related_query_name

Модуль 3: Django
9 уровень , 4 лекция
Открыта

На предыдущих лекциях мы познакомились с основными типами связей между моделями: OneToOne, ForeignKey и ManyToMany. Мы разобрались, как правильно удалять объекты, чтобы потом не пришлось кусать локти, а также узнали об оптимизации запросов с помощью методов select_related() и prefetch_related().

Теперь пора разобраться, как настроить обратный доступ к связанным объектам с помощью параметров related_name (имя обратной связи) и related_query_name (имя для обратных запросов).

В этой лекции мы узнаем, как настроить related_name для улучшения читаемости и удобства работы с обратными связями. Также разберемся с понятием related_query_name и его использованием в фильтрациях и обратных запросах.

Что такое related_name?

Когда мы создаём связь между двумя моделями, например через ForeignKey, Django автоматически добавляет "обратное" имя для доступа к связанным объектам. Однако это имя может быть не всегда удобным или интуитивно понятным.

Пример:

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.author
  • От автора ко всем его книгам: author.book_set.all()

Обратите внимание на book_set. Django автоматически создаёт это имя с добавлением _set к имени модели в нижнем регистре. Это полезно, но не всегда удобно.

Настройка related_name

Чтобы настроить имя обратной связи, мы можем использовать параметр related_name в полях ForeignKey или ManyToManyField.

Пример с related_name:

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

Теперь вместо author.book_set.all() можно использовать более читаемое author.books.all().

Основные преимущества related_name:

  1. Повышение читаемости кода: более понятные имена облегчают понимание кода.
  2. Избежание конфликтов: если у вас несколько связей между двумя моделями, вы можете настроить разные related_name для каждой связи.

Пример с несколькими связями:

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

class Article(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Editor, on_delete=models.CASCADE, related_name='authored_articles')
    reviewed_by = models.ForeignKey(Editor, on_delete=models.SET_NULL, null=True, related_name='reviewed_articles')

Здесь у редактора есть две роли:

  • Автор статей (editor.authored_articles.all()).
  • Рецензент статей (editor.reviewed_articles.all()).

Практический пример с использованием related_name

Создадим простую библиотечную систему:

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

class Book(models.Model):
    title = models.CharField(max_length=100)
    library = models.ForeignKey(Library, on_delete=models.CASCADE, related_name='books')

Теперь мы можем писать:

library = Library.objects.get(name="Городская библиотека")
books_in_library = library.books.all()  # Получение всех книг в библиотеке

Что такое related_query_name?

В предыдущем примере мы использовали related_name для доступа к связанным объектам. Но когда мы фильтруем объекты через связанные модели, Django автоматически присваивает имя фильтрации. Это имя может быть не очень описательным.

Пример фильтрации без related_query_name:

# Выбираем все библиотеки, где есть книга с названием "1984"
libraries_with_book = Library.objects.filter(books__title="1984")

Здесь books__title — это имя автоматически созданной обратной связи, соответствующей related_name или _set. Если имя связи становится сложным, мы можем использовать related_query_name для улучшения фильтрации.

Настройка related_query_name

Мы можем задать понятное имя для фильтраций через параметр related_query_name.

Пример использования related_query_name:

class Book(models.Model):
    title = models.CharField(max_length=100)
    library = models.ForeignKey(
        Library,
        on_delete=models.CASCADE,
        related_name='books',
        related_query_name='book'
    )

Теперь фильтрацию можно записать более явно:

libraries_with_book = Library.objects.filter(book__title="1984")

Отличие между related_name и related_query_name:

  • related_name используется для доступа к объектам (например, library.books.all()).
  • related_query_name используется только в фильтрах (например, Library.objects.filter(book__title="1984")).

Практический пример с использованием related_query_name

Добавим модель Author для работы с книгами и библиотеками:

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,
        related_name='books',
        related_query_name='book'
    )
    library = models.ForeignKey(
        Library,
        on_delete=models.CASCADE,
        related_name='books',
        related_query_name='library_book'
    )

Теперь мы можем выполнять запросы, используя заданные related_query_name:

# Фильтр всех авторов, которые написали книгу с названием "1984"
authors_with_book = Author.objects.filter(book__title="1984")

# Фильтр всех библиотек, содержащих книгу с названием "1984"
libraries_with_book = Library.objects.filter(library_book__title="1984")

Полезные советы и типичные ошибки

  1. Конфликты имён: если у вас много связей между одними и теми же моделями, используйте уникальные имена для related_name и related_query_name. Это избавит вас от ошибок "Ambiguous field name".

  2. Не путайте related_name и имя модели: часто начинающие разработчики путают related_name с именем модели. Помните, что related_name — это просто строка, которую вы задаёте по своему усмотрению.

  3. Не используйте пробелы или специальные символы в related_name: хотя Django позволяет задавать любые строки, старайтесь использовать осмысленные идентификаторы, чтобы не усложнять поддержку проекта.

  4. Не забывайте миграции: любое изменение related_name или related_query_name требует пересоздания миграций и применения их к базе данных.

Примеры для самостоятельной практики

  1. Создайте модель Publisher (Издатель) и свяжите её с моделью Book. Настройте related_name как published_books и выполните запрос для получения всех книг конкретного издателя.

  2. Настройте related_query_name для модели Author, чтобы можно было фильтровать книги по параметру author_book. Выполните запрос для получения всех авторов, написавших определённую книгу.

  3. Попробуйте использовать разные on_delete настройки CASCADE, SET_NULL совместно с related_name, чтобы понять, как они влияют на удаление объектов.

Теперь у вас есть инструменты как для организации чистого кода, так и для оптимизации запросов!

1
Задача
Модуль 3: Django, 9 уровень, 4 лекция
Недоступна
Настройка related_name
Настройка related_name
1
Задача
Модуль 3: Django, 9 уровень, 4 лекция
Недоступна
Использование related_query_name
Использование related_query_name
3
Опрос
Связи между моделями, 9 уровень, 4 лекция
Недоступен
Связи между моделями
Связи между моделями
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Андрей Уровень 57
19 ноября 2025
задача 1 не проходит валидатором даже правильный ответ