drf-Serializers
What is serializers?
serializers主要作用是将原生的Python数据类型(如 model querysets )转换为web中通用的JSON,XML或其他内容类型。
DRF 提供了一个Serializer类,它为您提供了种强大的通用方法来控制响应的输出,以及一个ModelSerializer 类,它为创建处理 model instance 和 serializers 提供了一个序列化的快捷方式。
Reference
How to Declaring Serializers?
序列化一个django model
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')
声明Serializers,可以用来序列化与反序列化对象 Comment的属性及值。
from rest_framework import serializers
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField() # 属性名称与类Comment名校相同
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
序列化及反序列化
序列化
from rest_framework import serializers
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField()
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
# 上面类似于如下python中的操作
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"}'
反序列化
反序列化是将json数据流解析为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)}
数据的落地
如果需要对经过认证的数据进行保存入库,需要实现对应 serializer的 create() 和 update() 方法
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField()
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
def create(self, validated_data): # validate_data 实际与 Comment一致,打散后为
return Comment(**validated_data)
def update(self, instance, validated_data): # drf serializer实现了对应的实例,instance是该serializer,vilidated是对应的属性
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
serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
# {'email': ['Enter a valid e-mail address.'], 'created': ['This field is required.']}
save()
save() 可以创建或更新一个实例(实例是值库中的行)。
# .save() will create a new instance.
serializer = CommentSerializer(data=data)
# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)
How to Use validate?
validate是值在反序列化数据时,需要对数据进行验证(如,长度,值,类型),即在数据落地前,对其制定的规则进行验证。
serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
# {'email': ['Enter a valid e-mail address.'], 'created': ['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> 方法进行自定义验证方式,该方法需要返回验证的值或触发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
类级别验证
如果需要对多个字段进行验证验证,需要在类中实现validate() 方法。该方法仅单个参数 data, 为验证的字段的字典。例如
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 start is before finish.
"""
if data['start'] > data['finish']:
raise serializers.ValidationError("finish must occur after start")
return data
忽略验证
注意:如在Serializer 的<field_name> 声明了参数required=False 则该字段不会进行验证。
指定验证器
Serializer 的<field_name> 还可以声明 validator,例如,
def multiple_of_ten(value):
if value % 10 != 0:
raise serializers.ValidationError('Not a multiple of ten')
class GameRecord(serializers.Serializer):
score = IntegerField(validators=[multiple_of_ten])
...
validator Reference
ModelSerializer
ModelSerializer,是drf为了方便实现好的可以直接用的Serializer。实现为:
- 将根据模型自动为您生成一组字段。
- 将自动为Serializer程序生成validator,例如 unique_together 验证器。
- 包括简单的实现默认的
.create()和.update()。
ModelSerializer的声明
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ['id', 'account_name', 'users', 'created']
Meta的说明
Meta 类,如名称可知,这是设置Serializer的一些元数据。包含Model,Filed, Validator等信息,例如声明一个Meta类。
class EventSerializer(serializers.Serializer):
name = serializers.CharField()
room_number = serializers.IntegerField(choices=[101, 102, 103, 201])
date = serializers.DateField()
class Meta:
# 通过在内部Meta类中声明validators来包含,如下所示:
validators = [
UniqueTogetherValidator(
queryset=Event.objects.all(),
fields=['room_number', 'date']
)
]
# 通过在内部Meta类中声明model来包含对应使用model,如下所示:
model = User
# fields 可以指定要序列化的字段,'__all__'为model中的所有字段
fields = ['username', 'email', 'profile']
exclude=['username'] # exclude是要排除的字段
注:从 3.3.0 版开始,必须提供以下属性之一
fields或exclude.
Serializer会在Meta中拿取自己对应的属性进行使用,例如
meta = getattr(self, 'Meta', None)
validators = getattr(meta, 'validators', None)
# assert <condition>,(..error message)
# 可以看到Meta和Meta.model必须要设置
assert hasattr(self, 'Meta'), (
'Class {serializer_class} missing "Meta" attribute'.format(
serializer_class=self.__class__.__name__
)
)
assert hasattr(self.Meta, 'model'), (
'Class {serializer_class} missing "Meta.model" attribute'.format(
serializer_class=self.__class__.__name__
)
)
if model_meta.is_abstract_model(self.Meta.model):
raise ValueError(
'Cannot use ModelSerializer with Abstract Models.'
)
其他用法
设置只读字段:字段属性中添加 read_only=True, 或者在Meta类中添加属性 中指定字段 read_only_fields 为列表。
Serializer的字段与字段属性属性
Reference
字段属性
read_only在创建或更新时改属性True字段都被忽略write_only仅为创建或更新时使用,序列化时不操作该字段required默认情况下,在反序列化时未提供字段会引发错误,如果不需要可以设置为Falsesource:- 用于序列化时,填充替代对应字段名称的作用
URLField(source='get_absolute_url') - 可以跨表
- 可以执行对象内方法。
- 用于序列化时,填充替代对应字段名称的作用
Many: 可以返回多个对象,而非一个,在objects.all时使用
字段类型
BooleanField()CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)文本字段EmailField(max_length=None, min_length=None, allow_blank=False)email字段RegexField(regex, max_length=None, min_length=None, allow_blank=False)正则表达式IPAddressField(protocol='both', unpack_ipv4=False, **options)IP地址SerializerMethodField(method_name=None)通过方法序列化,只读字段method_name序列化时通过方法的名称。默认为get_<field_name>.
drf-Serializers的更多相关文章
- django 之(一) --- DjangoRestFormwork
接口概念 IOP:面向接口编程,不再关注具体的实现:只关注输入.输出. http://www.ruanyifeng.com/blog/2018/10/restful-api-best-practice ...
- DRF框架之 serializers 序列化组件
1. 什么是序列化,其实在python中我们就学了序列化工具json工具,就是吧信息存为类字典形式 2. DRF框架自带序列化的工具: serializers 3. DRF框架 serializers ...
- drf序列化器serializers.SerializerMethodField()的用法
问题描述: 为什么DRF中有时候返回的json中图片是带域名的,有时候是不带域名的呢? 解析: 带域名的结果是在view中对模型类序列化的,DRF在序列化图片的时候 会检查上下文有没有request, ...
- drf框架serializers中ModelSerializer类简化序列化和反序列化操作
0905自我总结 drf框架serializers中ModelSerializer类 基于seriallizer类进行简化 https://www.cnblogs.com/pythonywy/p/11 ...
- DRF源码-serializers
class BaseSerializer(Field) """ The BaseSerializer class provides a minimal class whi ...
- 02.drf不使用serializers返回数据
drf 可以使用不经过model和serialzier的数据返回,也可以配置权限 class DashboardStatusViewset(viewsets.ViewSet): "" ...
- DRF如何序列化外键的字段
我觉得在有些应用场景下,这个操作是有用的,因为可以减少一个AJAX的请求,以增加性能. 当然,是二次请求,还是一次传输.这即要考虑用户体验,还要兼顾服务器性能. 一切是有条件的平衡吧.就算是一次传输, ...
- drf相关问题
drf自定义用户认证: 登录默认 使用django的ModelBackend,对用户名和密码进行验证.但我们平时登录网站时除了用户名也可以用邮箱或手机进行登录,这就需要我们自己扩展backend 一. ...
- django rest framework serializers
django rest framework serializers序列化 serializers是将复杂的数据结构变成json或者xml这个格式的 serializers有以下几个作用:- 将qu ...
随机推荐
- django中动态新建postgres数据库表
import psycopg2def create_new_table(table_id): conn = psycopg2.connect(database='Test', user='postgr ...
- Memcached 服务分布式集群如何实现?
特殊说明:Memcached 集群和 web 服务集群是不一样的,所有 Memcached 的数据总和才是数据库的数据.每台 Memcached 都是部分数据.(一台 memcached 的数据,就是 ...
- 使用 Spring 框架的好处是什么?
轻量:Spring 是轻量的,基本的版本大约 2MB.控制反转:Spring 通过控制反转实现了松散耦合,对象们给出它们的依 赖,而不是创建或查找依赖的对象们.面向切面的编程(AOP):Spring ...
- Java根路径设置(在获取本地路径时会获取到这个文件夹,,这样就可以专门放配置文件了)
在获取本地路径时会获取到这个文件夹,,这样就可以专门放配置文件了
- vulnhub mrRobot渗透笔记
mrRobot渗透笔记 靶机下载地址:https://www.vulnhub.com/entry/mr-robot-1,151/ kali ip 信息收集 首先依旧时使用nmap扫描靶机的ip地址 n ...
- mian中的argv调用时为什么不是*argv
c++main函数char * argv[]是个指针数组,元素是指针,为何argv[1]得到不是地址? 照我的理解char *argv[]保存的应该是一组指针,即地址,每个地址中保存的是char类型变 ...
- 用纯RUST手撸一个开源流媒体服务(RTMP/HTTPFLV/HLS)XIU
作者工作目前在音视频流媒体行业,用了大概一年的业余时间学习Rust,并且实现了一个简单的音视频流媒体服务,虽然据说Rust已经连续多年被评为最受程序员喜欢的语言,但是在国内还是比较冷门,作者比较看好R ...
- Amaze UI 模版中心上线丨十几款高质量优秀模版免费提供!
Amaze UI模版中心终于上线了,目前汇聚了包含企业门户.新闻资讯.管理后台等多个领域的模版,全都可以免费下载. Amaze UI模版中心后续还会增加更多的模版以及领域,请各位持续关注. 模版中心的 ...
- 记一次用mpvue框架搭建的小程序
介绍 mpvue (github 地址请参见)是一个使用 Vue.js 开发小程序的前端框架.框架基于 Vue.js 核心,mpvue 修改了Vue.js 的 runtime 和 compiler 实 ...
- call、apply和 bind的简单使用方法
- call.apply:在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. J ...