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() для мінімізації навантаження на базу даних.

Тепер, коли ви знаєте, як використовувати вкладені серіалізатори, давайте додамо їх у наш проєкт і почнемо експериментувати.

3
Опитування
Вступ до серіалізації даних, рівень 17, лекція 4
Недоступний
Вступ до серіалізації даних
Вступ до серіалізації даних
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ