JavaRush /Курсы /Модуль 3: Django /Вложенные сериализаторы в Django REST Framework

Вложенные сериализаторы в Django REST Framework

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

Представьте, что у вас есть две модели в базе данных: User и Profile. Пользователь может иметь один профиль (связь OneToOne). Если вы хотите вернуть данные пользователя вместе с данными его профиля в одном запросе, то вам нужен вложенный сериализатор. Он помогает включить поля связанных моделей в сериализованный результат.

Аналогия: представьте матрёшку — главная внешняя кукла содержит внутри ещё одну куклу, которая, в свою очередь, может содержать другую. Вот так и работают вложенные сериализаторы: один сериализатор может "вкладывать" в себя другой.

Практика: создание вложенных сериализаторов

Давайте создадим модели Author и Book, где каждый автор может написать несколько книг (связь ForeignKey). Наша цель — вернуть данные автора, включая список его книг.

from django.db import models

# Модель автора
class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)

    def __str__(self):
        return self.name

# Модель книги
class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)

    def __str__(self):
        return self.title

Обратите внимание на related_name='books' в поле author. Это упрощает доступ к книгам автора через обратную связь: например, author.books.all().

Создание сериализаторов

Теперь мы создадим два сериализатора: один для объекта книги BookSerializer, а другой для автора AuthorSerializer, который включает вложенный список книг.

from rest_framework import serializers
from .models import Author, Book

# Сериализатор для книги
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'title']

# Сериализатор для автора
class AuthorSerializer(serializers.ModelSerializer):
    books = BookSerializer(many=True)  # Вложенный сериализатор

    class Meta:
        model = Author
        fields = ['id', 'name', 'email', 'books']
  1. Мы создали BookSerializer для сериализации данных о книгах.
  2. В AuthorSerializer мы добавили поле books, которое содержит список вложенных объектов. Параметр many=True указывает, что поле содержит массив данных.

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

Для теста создадим нескольких авторов и их книги:

from myapp.models import Author, Book

# Создаем автора
author = Author.objects.create(name="Isaac Asimov", email="asimov@example.com")

# Создаем книги для автора
Book.objects.create(title="Foundation", author=author)
Book.objects.create(title="I, Robot", author=author)

Теперь воспользуемся AuthorSerializer, чтобы посмотреть, как выглядят данные:

from myapp.serializers import AuthorSerializer
from myapp.models import Author

author = Author.objects.get(name="Isaac Asimov")
serializer = AuthorSerializer(author)
print(serializer.data)

Результат:

{
    "id": 1,
    "name": "Isaac Asimov",
    "email": "asimov@example.com",
    "books": [
        {
            "id": 1,
            "title": "Foundation"
        },
        {
            "id": 2,
            "title": "I, Robot"
        }
    ]
}

Изменение вложенных данных

Вложенные сериализаторы позволяют не только отображать данные, но и создавать или обновлять связанные объекты.

Представим, что вы хотите добавить новую книгу через сериализатор. Для этого потребуется переопределить метод create().

class AuthorSerializer(serializers.ModelSerializer):
    books = BookSerializer(many=True)

    class Meta:
        model = Author
        fields = ['id', 'name', 'email', 'books']

    def create(self, validated_data):
        books_data = validated_data.pop('books')  # Убираем вложенные данные
        author = Author.objects.create(**validated_data)  # Создаем автора
        for book_data in books_data:
            Book.objects.create(author=author, **book_data)  # Создаем книги
        return author

Пример запроса на создание:

{
    "name": "George Orwell",
    "email": "orwell@example.com",
    "books": [
        {"title": "1984"},
        {"title": "Animal Farm"}
    ]
}

Результат: новый автор и его книги будут добавлены в базу.

Особенности работы с вложенными сериализаторами

Иногда вы можете захотеть сделать вложенные данные только для чтения. Для этого используйте параметр read_only=True:

class AuthorSerializer(serializers.ModelSerializer):
    books = BookSerializer(many=True, read_only=True)

    class Meta:
        model = Author
        fields = ['id', 'name', 'email', 'books']

Теперь книги не будут изменяться при использовании сериализатора для создания или обновления данных.

Производительность при работе с вложенными сериализаторами

Если вы сериализуете большое количество объектов с вложенными данными, это может привести к многочисленным запросам к базе данных. Чтобы избежать этого, используйте select_related() и prefetch_related():

authors = Author.objects.prefetch_related('books').all()
serializer = AuthorSerializer(authors, many=True)

Это значительно уменьшит количество запросов, которые делает ваше приложение, и ускорит работу.

Ошибка: "Got a TypeError: Object of type 'Book' is not JSON serializable".

Если вы забыли, что Serializer нужен для преобразования моделей в сериализуемые форматы, вы можете столкнуться с подобной ошибкой. Убедитесь, что все вложенные объекты обрабатываются через сериализаторы.

Рекомендации для работы

Когда использовать вложенные сериализаторы? Есть несколько основных кейсов:

  • Простые зависимости: когда необходимо показать связанные данные простым списком или объектом.
  • Чтение данных: когда вам нужно показать связанные данные клиенту.
  • Небольшие объемы данных: вложенные сериализаторы подходят для обработки небольших объемов данных. Для более сложных сценариев может потребоваться разделение запросов.

В реальной работе:

  1. Используйте вложенные сериализаторы для чтения данных, но избегайте сложной логики создания/обновления без необходимости.
  2. Основные сценарии обновлений лучше обрабатывать на уровне представлений (views).
  3. Оптимизируйте запросы с помощью select_related() и prefetch_related() для минимизации нагрузки на базу данных.

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

1
Задача
Модуль 3: Django, 17 уровень, 4 лекция
Недоступна
Создание вложенных сериализаторов
Создание вложенных сериализаторов
1
Задача
Модуль 3: Django, 17 уровень, 4 лекция
Недоступна
API для вывода данных с вложением
API для вывода данных с вложением
3
Опрос
Введение в сериализацию данных, 17 уровень, 4 лекция
Недоступен
Введение в сериализацию данных
Введение в сериализацию данных
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Дмитрий/MrJonson Уровень 62
5 ноября 2025
12 Вопрос в тесте: Какой параметр в JSON отвечает за сохранение нескольких вложенных объектов? Выберите один из вариантов: related_objects nested_data many linked Правильный ответ: ни один из предложенных. В JSON нет специального параметра для сохранения нескольких вложенных объектов. Эта функциональность обеспечивается структурой данных, а не отдельным параметром. В Django REST Framework используется параметр many=True many - это параметр DRF сериализатора, а не JSON Ребята из JavaRush наймите нормального специалиста который в школе уроки литературы и русского языка проводил не у пивного ларька. Честное слово иногда читаешь тексты ну плакать хочется.