序列化器允许将复杂数据(如查询集和模型实例)转换为可轻松渲染为 JSON、XML 或其他内容类型的原生 Python 数据类型。序列化器还提供反序列化功能,允许将解析后的数据转换回复杂类型,但在执行此操作之前会先验证传入的数据。

REST framework 中的序列化器与 Django 中的 FormModelForm 类非常相似。我们提供了一个 Serializer 类,它为您提供了强大且通用的方式来控制响应的输出,以及一个 ModelSerializer 类,它为创建处理模型实例和查询集的序列化器提供了便捷方法。

声明序列化器

我们先创建一个简单的对象用于示例:

from datetime import datetime

class Comment:
    def __init__(self, email, content, created=None):
        self.email = email
        self.content = content
        self.created = created or datetime.now()

comment = Comment(email='leila@example.com', content='foo bar')

我们声明一个序列化器,用于序列化和反序列化与 Comment 对象对应的数据。声明序列化器的方式与声明表单非常相似:

from rest_framework import serializers

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

序列化对象

现在我们可以使用 CommentSerializer 来序列化一条评论或评论列表。使用 Serializer 类的方式与使用 Form 类非常相似:

serializer = CommentSerializer(comment)
serializer.data
# {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}

此时,我们将模型实例转换为了 Python 原生数据类型。要完成序列化过程,我们需要将数据渲染为 json:

from rest_framework.renderers import JSONRenderer

json = JSONRenderer().render(serializer.data)
json
# b'{"email":"leila@example.com","content":"foo bar","created":"2016-01-27T15:17:10.375877"}'

反序列化对象

反序列化过程类似。首先我们将数据流解析为 Python 原生数据类型...

import io
from rest_framework.parsers import JSONParser

stream = io.BytesIO(json)
data = JSONParser().parse(stream)

...然后将这些原生数据类型恢复为经过验证的数据字典。

serializer = CommentSerializer(data=data)
serializer.is_valid()
# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}

保存实例

如果我们希望能够基于经过验证的数据返回完整的对象实例,则需要实现 create()update() 方法中的一个或两个。例如:

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

    def create(self, validated_data):
        return Comment(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        return instance

如果您的对象实例对应 Django 模型,您还需要确保这些方法将对象保存到数据库中。例如,如果 Comment 是一个 Django 模型,这些方法可能如下所示:

    def create(self, validated_data):
        return Comment.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        instance.save()
        return instance

现在,当反序列化数据时,我们可以通过调用 .save() 方法基于经过验证的数据返回一个对象实例。

comment = serializer.save()

调用 .save() 方法时,会根据实例化序列化器类时是否传递了现有实例来决定是创建一个新实例还是更新一个现有实例:

# .save() 将创建一个新实例。
serializer = CommentSerializer(data=data)

# .save() 将更新现有的 `comment` 实例。
serializer = CommentSerializer(comment, data=data)

.create().update() 方法都是可选的。您可以根据序列化器类的用途选择不实现、仅实现其中一个或两个都实现。

您可以点击 Serializers - Django REST framework 查看更多相关内容。


观复
16 声望1 粉丝

君子慎独,不欺暗室,卑以自牧,含章可贞