欢迎来到Louis的博客

人生三从境界:昨夜西风凋碧树,独上高楼,望尽天涯路。 衣带渐宽终不悔,为伊消得人憔悴。 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
扩大
缩小

02-序列化组件的使用及接口设计-上

一.简介

  对于我们自己开发来说,如果项目采用了前后端分离架构,就django项目而言,一般都会使用drf来进行我们的接口设计,目前前后端交互的过程中,目前最常用的数据交换格式就是json了,而原生的django是不会对请求头为application/json的数据进行处理的,而在前后端分离的项目中又大量用到了json,这样就需要大量的代码来进行序列化,反序列化的操作,所以为了解决这个问题,drf提供了专门的序列化器(Serializers)来做这个事情。

  序列化器允许将复杂的数据(如查询集和模型示例)转换为可以轻松渲染成json,xml或者其他内容类型的原生Python数据类型。序列器还提供反序列化,在验证传入的数据之后允许解析数据转换回复杂类型。

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

二.简单实现

1.序列化

import os

# Create your tests here.


# 如果要在单配置文件中使用django的组件,需要进行django的环境setting配置,这点看下manage.py就可以发现 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'serializers_practice.settings') from datetime import datetime class Comment(object): 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') from rest_framework import serializers # 创建序列化类 class CommentSerializer(serializers.Serializer): email = serializers.EmailField() content = serializers.CharField(max_length=200) created = serializers.DateTimeField()
serializer
= CommentSerializer(comment) print(serializer.data) # {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2018-12-08T09:41:21.445749Z'}

 

   我们可以发现序列化器的声明方式与form表单组件很相似,到这里我们已经将对象实例转换为Python的原生的数据类型,我们将数据渲染为json

from rest_framework.renderers import JSONRenderer

# 封装成标准的JSON
json = JSONRenderer().render(serializer.data)
print(json)

#b'{"email":"leila@example.com","content":"foo bar","created":"2018-12-08T09:54:01.105209Z"}'

 

2.反序列化

# 反序列化
from django.utils.six import BytesIO
from rest_framework.parsers import JSONParser

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

# 将一个流解析为原生的Python原生的数据类型,然后将这些数据类型恢复为验证数据的字典
verified_data = CommentSerializer(data=data)
if verified_data.is_valid():
    print(verified_data.data)
else:
    print(verified_data.errors)

 

三.验证

  在反序列化数据时,在尝试访问经过验证的数据或保存对象实例之前,总是需要调用 is_valid(),如果发生任何验证错误,.errors 属性将包含表示结果错误消息的字典

serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
# {'email': [u'Enter a valid e-mail address.'], 'created': [u'This field is required.']}
View Code  

引发无效数据的异常 

  .is_valid() 方法使用可选的 raise_exception 标志,如果存在验证错误,将会抛出 serializers.ValidationError 异常。

这些异常由 REST framework 提供的默认异常处理程序自动处理,默认情况下将返回 HTTP 400 Bad Request响应。

# Return a 400 response if the data was invalid.
serializer.is_valid(raise_exception=True)

字段级别验证 

  自定义字段级的验证,定义validate_<field_name>字段,类似form表单组件中用于自定义校验的钩子函数。

  validate_<field_name> 方法应该返回已验证的值或者抛出 serializers.ValidationError 异常

from rest_framework import serializers

class BlogPostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    content = serializers.CharField()

    def validate_title(self, value):
        """
        Check that the blog post is about Django.
        """
        if 'django' not in value.lower():
            raise serializers.ValidationError("Blog post is not about Django")
        return value
View Code

  如果在您的序列化器上声明了 <field_name> 的参数为 required=False,那么如果不包含该字段,则此验证步骤不会发生。

对象级别验证

  全局的自定义校验,使用.validate(),方法接收单个参数,该参数为校验单个对象所反序列化的字典,如果需要,它应该抛出 ValidationError 异常,或者只返回经过验证的值。例如:

from rest_framework import serializers

class EventSerializer(serializers.Serializer):
    description = serializers.CharField(max_length=100)
    start = serializers.DateTimeField()
    finish = serializers.DateTimeField()

    def validate(self, data):
        """
        Check that the start is before the stop.
        """
        if data['start'] > data['finish']:
            raise serializers.ValidationError("finish must occur after start")
        return data
View Code

四.访问初始数据和实例

将初始化对象或者查询集传递给序列化器实例时,该对象将以 .instance 的形式提供。如果没有传递初始化对象,那么 .instance 属性将是 None

将数据传递给序列化器实例时,未修改的数据将以 .initial_data 的形式提供。如果 data 关键字参数未被传递,那么 .initial_data 属性将不存在。

 

posted on 2018-12-07 08:28  Louiszj  阅读(104)  评论(0编辑  收藏  举报

导航