Как использовать сериализаторы в веб-платформе Django Python
Сериализация - это процесс преобразования данных в формат, который может быть сохранен или передан, с последующим его восстановлением. Он постоянно используется при разработке приложений или хранении данных в базах данных, в памяти или преобразовании их в файлы.
Предположим, вы создаете программное обеспечение для сайта электронной коммерции и у вас есть Заказ, в котором регистрируется покупка одного продукта кем-то по указанной цене, на определенную дату:
class Order:
def __init__(self, product, customer, price, date):
self.product = product
self.customer = customer
self.price = price
self.date = date
Теперь представьте, что вы хотите сохранить и получить данные о заказе из базы данных «ключ-значение». К счастью, его интерфейс принимает и возвращает словари, поэтому вам нужно преобразовать свой объект в словарь:
def serialize_order(order):
return {
'product': order.product,
'customer': order.customer,
'price': order.price,
'date': order.date
}
И если вы хотите получить некоторые данные из этой базы данных, вы можете получить данные dict и превратить их в свой объект Order:
def deserialize_order(order_data):
return Order(
product=order_data['product'],
customer=order_data['customer'],
price=order_data['price'],
date=order_data['date'],
)
Это довольно просто сделать с простыми данными, но когда вам нужно иметь дело со сложными объектами, состоящими из сложных атрибутов, этот подход плохо масштабируется. Вам также необходимо выполнить проверку различных типов полей, а это придется делать вручную.
Вот где пригодятся сериализаторы фреймворков. Они позволяют создавать сериализаторы с небольшими шаблонами, которые будут работать в ваших сложных случаях.
Django поставляется с модулем сериализации, который позволяет «переводить» модели в другие форматы:
from django.core import serializers
serializers.serialize('json', Order.objects.all())
Он охватывает наиболее часто используемые случаи для веб-приложений, таких как JSON, YAML и XML. Но вы также можете использовать сторонние сериализаторы или создать свои собственные. Вам просто нужно зарегистрировать его в своем файле settings.py:
SERIALIZATION_MODULES = {
'my_format': appname.serializers.MyFormatSerializer,
}
Чтобы создать свой собственный MyFormatSerializer
, вам необходимо реализовать метод .serialize()
и принять набор запросов и дополнительные параметры в качестве параметров:
class MyFormatSerializer:
def serialize(self, queryset, **options):
# serious serialization happening
Теперь вы можете сериализовать свой запрос в новый формат:
from django.core import serializers
serializers.serialize('my_format', Order.objects.all())
Вы можете использовать параметры options, чтобы определить поведение сериализатора. Например, если вы хотите определить, что вы собираетесь работать с вложенной сериализацией при работе с ForeignKeys
, или вы просто хотите, чтобы эти данные возвращали свои первичные ключи, вы можете передать параметр flat=True
в качестве опции и обработать его в своем методе:
class MyFormatSerializer:
def serializer(self, queryset, **options):
if options.get('flat', False):
# don't recursively serialize relationships
# recursively serialize relationships
Один из способов использования сериализации Django - это команды управления loaddata
и dumpdata
.
Сериализаторы DRF
В сообществе Django фреймворк Django REST (DRF) предлагает самые известные сериализаторы. Хотя вы можете использовать сериализаторы Django для создания JSON, на который вы будете отвечать в своем API, один из фреймворка REST имеет приятные функции, которые помогут вам справиться и легко проверить сложные данные.
В примере заказа вы можете создать сериализатор следующим образом:
from restframework import serializers
class OrderSerializer(serializers.Serializer):
product = serializers.CharField(max_length=255)
customer = serializers.CharField(max_lenght=255)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
date = serializers.DateField()
И легко сериализуйте его данные:
order = Order('pen', 'renato', 10.50, date.today())
serializer = OrderSerializer(order)
serializer.data
# {'product': 'pen', 'customer': 'renato', 'price': '10.50', 'date': '2020-08-16'}
Чтобы иметь возможность возвращать экземпляр из данных, вам необходимо реализовать два метода - create и update:
from rest_framework import serializers
class OrderSerializer(serializers.Serializer):
product = serializers.CharField(max_length=255)
customer = serializers.CharField(max_length=255)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
date = serializers.DateField()
def create(self, validated_data):
# perform order creation
return order
def update(self, instance, validated_data):
# perform instance update
return instance
После этого вы можете создавать или обновлять экземпляры, вызывая is_valid()
для проверки данных и save()
для создания или обновления экземпляра:
serializer = OrderSerializer(**data)
## to validate data, mandatory before calling save
serializer.is_valid()
serializer.save()
Сериализаторы моделей
При сериализации данных вам часто нужно делать это из базы данных, следовательно, из ваших моделей. ModelSerializer, как и ModelForm, предоставляет API для создания сериализаторов из ваших моделей. Предположим, у вас есть модель заказа:
from django.db import models
class Order(models.Model):
product = models.CharField(max_length=255)
customer = models.CharField(max_length=255)
price = models.DecimalField(max_digits=5, decimal_places=2)
date = models.DateField()
Вы можете создать для него сериализатор следующим образом:
from rest_framework import serializers
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = '__all__'
Django автоматически включает в себя все модели поля в сериализатор и создает методы create
и update
.
Использование сериализаторов в представлениях на основе классов (CBV)
Как и формы с CBV от Django, сериализаторы хорошо интегрируются с DRF. Вы можете установить атрибут serializer_class
так, чтобы сериализатор был доступен для представления:
from rest_framework import generics
class OrderListCreateAPIView(generics.ListCreateAPIView):
queryset = Order.objects.all()
serializer_class = OrderSerializer
Вы также можете определить метод get_serializer_class()
:
from rest_framework import generics
class OrderListCreateAPIView(generics.ListCreateAPIView):
queryset = Order.objects.all()
def get_serializer_class(self):
if is_free_order():
return FreeOrderSerializer
return OrderSerializer
В CBV есть и другие методы, которые взаимодействуют с сериализаторами. Например, get_serializer()
возвращает уже созданный сериализатор, а get_serializer_context()
возвращает аргументы, которые вы передадите сериализатору при создании его экземпляра.