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.']}
引发无效数据的异常
.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
如果在您的序列化器上声明了 <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
四.访问初始数据和实例
将初始化对象或者查询集传递给序列化器实例时,该对象将以 .instance
的形式提供。如果没有传递初始化对象,那么 .instance
属性将是 None
。
将数据传递给序列化器实例时,未修改的数据将以 .initial_data
的形式提供。如果 data 关键字参数未被传递,那么 .initial_data
属性将不存在。