Оволодіння серіалізаторами Django REST Framework: від основ до найкращих практик

pic

Серіалізатори (serializers) у Django REST Framework (DRF) є основним інструментом для перетворення складних типів даних, таких як екземпляри моделей або Querysets, у зручні для роботи типи даних Python, а потім у формати, зручні для відправки через API, такі як JSON. Вони також допомагають виконувати зворотне перетворення: приймати дані у форматі JSON, перевіряти їх на коректність і перетворювати на Python об'єкти або екземпляри моделей, які можна зберігати в базі даних.

Серіалізатор можна порівняти з формами Django: форми перетворюють введення користувача з HTML форм на Python об'єкти, а серіалізатори — з JSON в Python об'єкти і навпаки.

Іноді ви не працюєте з моделями, а просто серіалізуєте або перевіряєте прості структури даних. Для таких випадків підходить клас Serializer в DRF. Наприклад, можна створити простий клас Python для опису книги:

Простий клас Python, не пов'язаний з моделями Django!

class Book:
def init(self, title, author):
self.title = title
self.author = author

Далі за допомогою серіалізатора ми можемо визначити, як ці дані мають бути перетворені у формат JSON та назад:

from rest_framework import serializers

class BookSerializer(serializers.Serializer):
title = serializers.CharField(maxlength=100)
author = serializers.CharField(max
length=100)

Це дозволяє нам серіалізувати дані та десеріалізувати їх назад у Python об'єкти з перевіркою на коректність:

book = Book(title="Django for Beginners", author="William S. Vincent")
serializer = BookSerializer(book)
print(serializer.data)

Вихід: {'title': 'Django for Beginners', 'author': 'William S. Vincent'}

Якщо передати некоректні дані, наприклад, порожні поля, серіалізатор повідомить про помилку:

invaliddata = {'title': '', 'author': ''}
serializer = BookSerializer(data=invalid
data)
print(serializer.is_valid()) # False
print(serializer.errors)

{'title': ['This field may not be blank.'], 'author': ['This field may not be blank.']}

Коли ви працюєте з моделями Django, найкраще використовувати ModelSerializer, який автоматично генерує серіалізатори для всіх полів моделі, зменшуючи кількість шаблонного коду:

models.py

from django.db import models

class Book(models.Model):
title = models.CharField(maxlength=100)
author = models.CharField(max
length=100)
published = models.DateField()

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = 'all'

ModelSerializer автоматично генерує поля на основі вашої моделі та дозволяє працювати з даними безпосередньо через API.

Якщо ви хочете налаштувати логіку створення або оновлення об'єкта моделі, ви можете переозначити методи create() та update():

def create(self, validateddata):
return Book.objects.create(**validated
data)

def update(self, instance, validateddata):
instance.title = validated
data.get('title', instance.title)
instance.author = validateddata.get('author', instance.author)
instance.published = validated
data.get('published', instance.published)
instance.save()
return instance

DRF автоматично генерує ці методи, якщо ви їх не переозначите.

Ключовою частиною серіалізаторів є валідація даних. DRF обробляє типові правила валідації, такі як обов'язковість полів, максимальна та мінімальна довжина, форматування дат та вибір з набору значень. Ви можете перевірити дані через метод is_valid() і отримати повідомлення про помилки:

data = {'title': '', 'author': 'Some Author'}
serializer = BookSerializer(data=data)
print(serializer.is_valid()) # False
print(serializer.errors)

{'title': ['This field may not be blank.']}

Якщо вам потрібно додати свою логіку валідації, ви можете використовувати методи для валідації окремих полів та для перевірки кількох полів одночасно:

def validate(self, data):
if data['title'].lower() == data['author'].lower():
raise serializers.ValidationError("Title and author can't be the same.")
return data

DRF також підтримує вкладені серіалізатори (Nested Serializers), що дозволяє працювати з відносинами між моделями. Наприклад, якщо у вас є автор, який має багато книг, ви можете серіалізувати ці відносини:

models.py

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

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

class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['id', 'name']

class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer()

class Meta:
model = Book
fields = ['id', 'title', 'author']

Це дасть результат у вигляді вкладених об'єктів:

{
"id": 1,
"title": "Django Unleashed",
"author": {
"id": 1,
"name": "Andrew Pinkham"
}
}

Якщо ви хочете працювати з зворотними відносинами (наприклад, щоб отримати всі книги автора), можна додати поле, яке буде повертати всі пов'язані об'єкти:

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

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

В результаті ви отримаєте всі книги цього автора в серіалізаторі:

{
"id": 1,
"name": "William S. Vincent",
"books": [
{"id": 1, "title": "Django for Beginners"},
{"id": 2, "title": "Django for APIs"}
]
}

Для роботи з полями, які повинні бути тільки для читання або тільки для запису, DRF надає можливість використовувати властивості read_only=True та write_only=True. Це корисно, наприклад, для поля пароля, яке не повинно бути відображено в результаті, але має бути прийняте на вході:

class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)

class Meta:
model = User
fields = ['username', 'email', 'password']

Нарешті, DRF підтримує часткові оновлення, де можна оновити лише частину полів моделі, використовуючи параметр partial=True:

serializer = BookSerializer(book_instance, data=request.data, partial=True)

Це дозволяє пропустити перевірку обов'язкових полів, якщо вони відсутні в запиті.

Серіалізатори є основою Django REST Framework і необхідні для створення API, які будуть чистими, масштабованими і ефективними. Освоєння їх дає вам потужний інструмент для роботи з даними у Django.

Перекладено з: Mastering Django REST Framework Serializers: From Basics to Best Practices