如何在 Python Web 框架 Django 中使用序列化器
序列化

> 
> 序列化用于将数据转换为方便存储或传输的格式，然后将其重新构建以供使用。DRF 是最具有知名的序列化器。
> 
> 
> 


![](/data/attachment/album/202012/08/220845q5tz7cfftze5oem5.jpg)


序列化是将数据转换为可以存储或传输的格式，然后对其进行重新构建的过程。在开发应用程序或将数据存储在数据库、内存或将其转换为文件时，一直会用到它。


我最近帮助 [Labcodes](http://www.labcodes.com.br) 的两名初级开发人员理解序列化器，我想也可以与诸位读者分享一下我的方法。


假设你正在编写一个电子商务网站，你有一个订单，该订单记录了某人在某个日期以某种价格购买了一个产品：



```
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
    }

```

如果你想从数据库中获取一些数据，你可以获取字典数据并将其转换为订单对象（`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](https://www.djangoproject.com/) 提供了一个序列化模块，允许你将模型“转换”为其它格式：



```
from django.core import serializers

serializers.serialize('json', Order.objects.all())

```

它涵盖了 Web 应用程序最常用的种类，例如 JSON、YAML 和 XML。但是你也可以使用第三方序列化器或创建自己的序列化器。你只需要在 `settings.py` 文件中注册它：



```
# 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())

```

你可以使用选项参数来定义序列化程序的行为。例如，如果要定义在处理 `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 框架](https://www.django-rest-framework.org/)（DRF）提供了最著名的序列化器。尽管你可以使用 Django 的序列化器来构建将在 API 中响应的 JSON，但 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):
        # 执行订单创建
        return order

    def update(self, instance, validated_data):
       # 执行实例更新
       return instance

```

之后，你可以通过调用 `is_valid()` 来验证数据，并通过调用 `save()` 来创建或更新实例：



```
serializer = OrderSerializer(**data)
## 若要验证数据，在调用 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` 和 `udpate` 方法。


### 在基于类的视图（CBV）中使用序列化器


像 Django CBV 中的 `Forms` 一样，序列化器可以很好地与 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()](http://www.cdrf.co/3.9/rest_framework.generics/CreateAPIView.html#get_serializer) 返回一个已经实例化的序列化器，[get\_serializer\_context()](http://www.cdrf.co/3.9/rest_framework.generics/CreateAPIView.html#get_serializer_context) 返回创建实例时传递给序列化器的参数。对于创建或更新数据的视图，有 `create` 和 `update`，它们使用 `is_valid` 方法验证数据，还有 [perform\_create](http://www.cdrf.co/3.9/rest_framework.generics/CreateAPIView.html#perform_create) 和 [perform\_update](http://www.cdrf.co/3.9/rest_framework.generics/RetrieveUpdateAPIView.html#perform_update) 调用序列化器的 `save` 方法。


### 了解更多


要了解更多资源，参考我朋友 André Ericson 的[经典 Django REST 框架](http://www.cdrf.co/)网站。它是一个[基于类的经典视图](https://ccbv.co.uk/)的 REST 框架版本，可让你深入查看组成 DRF 的类。当然，官方[文档](https://www.django-rest-framework.org/api-guide/serializers/#serializers)也是一个很棒的资源。




---


via: <https://opensource.com/article/20/11/django-rest-framework-serializers>


作者：[Renato Oliveira](https://opensource.com/users/renato-oliveira) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
Serialization is the process of transforming data into a format that can be stored or transmitted and then reconstructing it. It's used all the time when developing applications or storing data in databases, in memory, or converting it into files.

I recently helped two junior developers at [Labcodes](http://www.labcodes.com.br) understand serializers, and I thought it would be good to share my approach with Opensource.com readers.

Suppose you're creating software for an e-commerce site and you have an Order that registers the purchase of a single product, by someone, at a price, on a date:

```
class Order:
def __init__(self, product, customer, price, date):
self.product = product
self.customer = customer
self.price = price
self.date = date
```


Now, imagine you want to store and retrieve order data from a key-value database. Luckily, its interface accepts and return dictionaries, so you need to convert your object into a dictionary:

```
def serialize_order(order):
return {
'product': order.product,
'customer': order.customer,
'price': order.price,
'date': order.date
}
```


And if you want to get some data from that database, you can get the dict data and turn that into your Order object:

```
def deserialize_order(order_data):
return Order(
product=order_data['product'],
customer=order_data['customer'],
price=order_data['price'],
date=order_data['date'],
)
```


This is pretty straightforward to do with simple data, but when you need to deal with complex objects made of complex attributes, this approach doesn't scale well. You also need to handle the validation of different types of fields, and that's a lot of work to do manually.

That's where frameworks' serializers are handy. They allow you to create serializers with little boilerplates that will work for your complex cases.

[Django](https://www.djangoproject.com/) comes with a serialization module that allows you to "translate" Models into other formats:

```
from django.core import serializers
serializers.serialize('json', Order.objects.all())
```


It covers the most-used cases for web applications, such as JSON, YAML, and XML. But you can also use third-party serializers or create your own. You just need to register it in your settings.py file:

```
# settings.py
SERIALIZATION_MODULES = {
'my_format': appname.serializers.MyFormatSerializer,
}
```


To create your own `MyFormatSerializer`

, you need to implement the `.serialize()`

method and accept a queryset and extra options as params:

```
class MyFormatSerializer:
def serialize(self, queryset, **options):
# serious serialization happening
```


Now you can serialize your queryset to your new format:

```
from django.core import serializers
serializers.serialize('my_format', Order.objects.all())
```


You can use the options parameters to define the behavior of your serializer. For example, if you want to define that you're going to work with nested serialization when dealing with `ForeignKeys`

or you just want that data to return its primary keys, you can pass a `flat=True`

param as an option and deal with that within your method:

```
class MyFormatSerializer:
def serializer(self, queryset, **options):
if options.get('flat', False):
# don't recursively serialize relationships
# recursively serialize relationships
```


One way to use Django serialization is with the `loaddata`

and `dumpdata`

management commands.

## DRF serializers

In the Django community, the [Django REST framework](https://www.django-rest-framework.org/) (DRF) offers the best-known serializers. Although you can use Django's serializers to build the JSON you'll respond to in your API, the one from the REST framework comes with nice features that help you deal with and easily validate complex data.

In the Order example, you could create a serializer like this:

```
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()
```


And easily serialize its data:

```
order = Order('pen', 'renato', 10.50, date.today())
serializer = OrderSerializer(order)
serializer.data
# {'product': 'pen', 'customer': 'renato', 'price': '10.50', 'date': '2020-08-16'}
```


To be able to return an instance from data, you need to implement two methods—create and 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
```


After that, you can create or update instances by calling `is_valid()`

to validate the data and `save()`

to create or update an instance:

```
serializer = OrderSerializer(**data)
## to validate data, mandatory before calling save
serializer.is_valid()
serializer.save()
```


## Model serializers

When serializing data, you often need to do it from a database, therefore, from your models. A ModelSerializer, like a ModelForm, provides an API to create serializers from your models. Suppose you have an Order model:

```
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()
```


You can create a serializer for it like this:

```
from rest_framework import serializers
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = '__all__'
```


Django automatically includes all model fields in the serializer and creates the `create`

and `update`

methods.

## Using serializers in class-based views (CBVs)

Like Forms with Django's CBVs, serializers integrate well with DRFs. You can set the `serializer_class`

attribute so that the serializer will be available to the view:

```
from rest_framework import generics
class OrderListCreateAPIView(generics.ListCreateAPIView):
queryset = Order.objects.all()
serializer_class = OrderSerializer
```


You can also define the `get_serializer_class()`

method:

```
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
```



There are other methods in CBVs that interact with serializers. For example, [get_serializer()](http://www.cdrf.co/3.9/rest_framework.generics/CreateAPIView.html#get_serializer) returns an already-instantiated serializer, while [get_serializer_context()](http://www.cdrf.co/3.9/rest_framework.generics/CreateAPIView.html#get_serializer_context) returns the arguments you'll pass to the serializer when creating its instance. For views that create or update data, there are `create`

and `update`

that validate the data with the `is_valid`

method to be saved, and [perform_create](http://www.cdrf.co/3.9/rest_framework.generics/CreateAPIView.html#perform_create) and [perform_update](http://www.cdrf.co/3.9/rest_framework.generics/RetrieveUpdateAPIView.html#perform_update) that call the serializer's save method.

## Learn more

For other resources, see my friend André Ericson's [Classy Django REST Framework](http://www.cdrf.co/) website. It is a [Classy Class-Based Views](https://ccbv.co.uk/) REST Framework version that gives you an in-depth inspection of the classes that compose DRF. Of course, the official [documentation](https://www.django-rest-framework.org/api-guide/serializers/#serializers) is an awesome resource.

## Comments are closed.