Серіалізатори (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(maxlength=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=invaliddata)
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(maxlength=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(**validateddata)
def update(self, instance, validateddata):
instance.title = validateddata.get('title', instance.title)
instance.author = validateddata.get('author', instance.author)
instance.published = validateddata.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, relatedname='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