Django Rest Framework(2)-----序列化详解(serializers)
REST framework中的序列化类与Django的Form和ModelForm类非常相似。我们提供了一个Serializer类,它提供了一种强大的通用方法来控制响应的输出,以及一个ModelSerializer类,它为创建处理模型实例和查询集的序列化提供了有效的快捷方式。
Serializers
序列化器允许把像查询集和模型实例这样的复杂数据转换为可以轻松渲染成JSON,XML或其他内容类型的原生Python类型。序列化器还提供反序列化,在验证传入的数据之后允许解析数据转换回复杂类型。不仅仅有序列化功能,更提供了数据验证的功能(与django中的form类似)
牛刀小试:
让我们从创建一个简单的对象开始,我们可以使用下面的例子:
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')
然后声明一个序列化器,我们可以使用它来序列化和反序列化与Comment对象相应的数据。
声明一个序列化器看起来非常像声明一个form:
from rest_framework import serializers class CommentSerializer(serializers.Serializer):
email = serializers.EmailField()
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
1、序列化与反序列化
# 序列化(Python原生的数据类型dict)
serializer = CommentSerializer(comment)
serializer.data # {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}
#转化为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"}' # 反序列化
from django.utils.six import BytesIO
from rest_framework.parsers import JSONParser stream = BytesIO(json)
data = JSONParser().parse(stream)
2、保存实例
如果我们希望能够返回基于验证数据的完整对象实例,我们需要实现其中一个或全部实现.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)
# return Comment.objects.create(**validated_data) # model对象 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() model对象
return instance
ps:.create()和.update()方法都是可选的。你可以根据你序列化器类的用例不实现、实现它们之一或都实现。
现在当我们反序列化数据的时候,基于验证过的数据我们可以调用.save()方法返回一个对象实例。
comment = serializer.save()
调用.save()方法将创建新实例或者更新现有实例,具体取决于实例化序列化器类的时候是否传递了现有实例:
# .save() will create a new instance.
serializer = CommentSerializer(data=data) # .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)
默认情况下,序列化程序必须为所有必填字段传递值,否则会引发验证错误。你可以使用partial参数以允许部分更新
# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data,partial=True)
3、验证
反序列化数据的时候,你始终需要先调用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.']}
字典里的每一个键都是字段名称,值是与该字段对应的任何错误消息的字符串列表。non_field_errors键可能存在,它将列出任何一般验证错误信息。non_field_errors的名称可以通过REST framework设置中的NON_FIELD_ERRORS_KEY来自定义。 当对对象列表进行序列化时,返回的错误是每个反序列化项的字典列表。
抛出无效数据的异常
.is_valid()方法使用可选的raise_exception标志,如果存在验证错误将会抛出一个serializers.ValidationError异常。
这些异常由REST framework提供的默认异常处理程序自动处理,默认情况下将返回HTTP 400 Bad Request响应。
# 如果数据无效就返回400响应
serializer.is_valid(raise_exception=True)
字段级别的验证
你可以通过向你的Serializer子类中添加.validate_<field_name>方法来指定自定义字段级别的验证。这些类似于Django表单中的.clean_<field_name>方法。
这些方法采用单个参数,即需要验证的字段值。
你的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()方法到你的Serializer子类中。这个方法采用字段值字典的单个参数,如果需要应该抛出一个 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
验证器
序列化器上的各个字段都可以包含验证器,通过在字段实例上声明,例如:
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])
序列化器类还可以包括应用于一组字段数据的可重用的验证器。validators给我们提供了很多很好的功能:UniqueValidator,UniqueTogetherValidator等。
这些验证器要在内部的Meta类中声明,如下所示:
UniqueTogetherValidator:(表示联合唯一)
class EventSerializer(serializers.Serializer):
name = serializers.CharField()
room_number = serializers.IntegerField(choices=[101, 102, 103, 201])
date = serializers.DateField() class Meta:
# 每间屋子每天只能有1个活动。
validators = UniqueTogetherValidator(
queryset=Event.objects.all(),
fields=['room_number', 'date']
)
UniqueValidator:
username = serializers.CharField(
max_length=11,
min_length=11,
validators=[UniqueValidator(queryset=UserProfile.objects.all())
)
更多信息请参阅 validators文档。
ModelSerializer
它为创建用于处理模型实例和查询集的序列化程序提供了有用的快捷实现方式。自动创建一个Serializer类,字段与model的字段一一对应。
ModelSerializer类与常规Serializer类相同,不同之处在于:
- 它会根据模型自动生成一组字段。
- 它会自动为序列化类生成验证器,例如unique_together验证器。
- 它包含.create()和.update()的简单默认实现。它能够满足将post或patch上来的数据进行进行直接地创建与更新,除非有额外需求,那么就可以重载create与update方法。
声明ModelSerializer如下,在Meta中设置fields字段,系统会自动进行映射成序列化字段,省去每个字段再写一个field。
1、序列化
class CourseSerializer(serializers.ModelSerializer):
"""
课程序列化
"""class Meta:
model = models.Course
# 字段显示
fields = ['id','title','level'] #
# fields = '__all__': 表示所有字段
# exclude = ('add_time',): 除去指定的某些字段
# 只读字段 ---多个字段只读,我们可以这样设置,不用每个字段都设置read_only=True
read_only_fields=(“field_name”,) # editable=False、AutoField 默认只读,不用添加
2、关于外键
任何关系(如模型上的外键)都将映射到PrimaryKeyRelatedField(但获得外键类别的id)。除非在序列化关系文档中指定,否则默认不包括反向关系。
class CourseDetailSerializer(serializers.ModelSerializer):
"""
课程详细序列化
"""
# choice
level = serializers.CharField(source='course.get_level_display')
# one2one/fk
# 外键方式一 需要单个信息
title = serializers.ReadOnlyField(source='course.title')
# 外键方式二 需要更多信息
course=CourseSerializer(many=True) # m2m 方法一:使用SerializerMethodField(method_name=None)方法,but该方法为readonly字段。
#---当不指定method_name ,默认为get_field_name,
recommends = serializers.SerializerMethodField()
chapter = serializers.SerializerMethodField() class Meta:
model = models.CourseDetail
fields = ['course','title','img','level','slogon','why','recommends','chapter']
# 外键方式三 depth 表示应该遍历的关联深度
# depth = 1 另外访问时显示外键字段的所有信息,但是只读的,不可编辑,即新建时不能传值
def get_recommends(self,obj): # 获取推荐的所有课程
queryset = obj.recommend_courses.all()
return [{'id':row.id,'title':row.title} for row in queryset] def get_chapter(self,obj): # 获取推荐的所有课程
queryset = obj.course.chapter_set.all()
return [{'id':row.id,'name':row.name} for row in queryset]
ModelSerializer主要需要解决的2个问题:
如在用户注册时,我们需要填写验证码,这个验证码只需要验证,不需要保存到用户这个Model中:
def validate(self, attrs):
del attrs["code"]
return attrs
假设需要返回用户加入这个网站多久了,不可能维持这样加入的天数这样一个数据,一般会记录用户加入的时间点,然后当用户获取这个数据,我们再计算返回给它。
class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField() class Meta:
model = User # 方法写法:get_ + 字段
def get_days_since_joined(self, obj):
# obj指这个model的对象
return (now() - obj.date_joined).days
Django Rest Framework(2)-----序列化详解(serializers)的更多相关文章
- Django Rest framework 之 序列化
RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...
- Django REST Framework的序列化器是什么?
# 转载请留言联系 用Django开发RESTful风格的API存在着很多重复的步骤.详细可见:https://www.cnblogs.com/chichung/p/9933861.html 过程往往 ...
- Django之form表单详解
构建一个表单 假设你想在你的网站上创建一个简单的表单,以获得用户的名字.你需要类似这样的模板: <form action="/your-name/" method=" ...
- Django路由配置之正则表达式详解
正则表达式详解 urls.py from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles ...
- django-插件django REST framework,返回序列化的数据
官网: http://www.django-rest-framework.org 1.安装 pip install djangorestframework 2.在setting.py中注册app 中添 ...
- Django restful Framework 之序列化与反序列化
1. 首先在已建好的工程目录下新建app命名为snippets,并将snippets app以及rest_framework app加到工程目录的 INSTALLED_APPS 中去,具体如下: IN ...
- Django rest framework之序列化小结
最近在DRF的序列化上踩过了不少坑,特此结合官方文档记录下,方便日后查阅. [01]前言 serializers是什么?官网是这样的”Serializers allow complex d ...
- rest_framework之序列化详解 06
拿到所有的角色数据 1.urls.py 2.models.py 假设只有3个角色 3.views.py from api import models import json json只能序列化pyt ...
- DRF Django REST framework 之 序列化(三)
Django 原生 serializer (序列化) 导入模块 from django.core.serializers import serialize 获取queryset 对queryset进行 ...
随机推荐
- 编译ros程序包--4
编译程序包(原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/) 1.编译程序包: 一旦安装了所需的系统依赖项,我们就可以开始编译刚才创建的程序包了 ...
- 在WCF中实现双工通信
双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...
- C# GetType和typeof的区别
typeof: The typeof operator is used to obtain the System.Type object for a type. 运算符,获得某一类型的 System. ...
- Mysql课后思考题
1.请简述数据库.表和数据库服务器之间的关系? 知识点数据库存储结构 一个数据库服务器可以管理多个数据库,通常情况下开发人员会针对每个应用创建一个数据库,为保存应用中实体的数据,会在数据库中创建多个表 ...
- SegmentedControl的使用
原文 http://blog.csdn.net/hmt20130412/article/details/38390493 @UISegmentedControl类似于UIButton,它可以提供多个选 ...
- python2.0_s12_day19_前端模版使用
Django中引用bootstrap实现在前端可以创建客户信息,可以修改客户信息我们需要设计一个前端用户交互系统.我们在设计之前,讨论一些需求:前端实现:1. 不同角色的用户,看到的东西是不一样的 销 ...
- java -jar Test.jar找不到main class问题
如果你写了一些class,编 译到一个jar里面,但是在执行这个jar的时候报错,找不到main class,但是你明明是有的,是不是很郁闷,检查一下你的jar吧. 解压你的jar,打开META-IN ...
- vs2008设置dll、lib库的输出路径
vs2008中,有些项目上的功能是要生产库文件给其他项目调用的,以下是一些设置库文件(x.dll和x.lib)输出路径的方法. 设置x.dll 输出路径方法是在右键项目的"属性"- ...
- Android App签名打包 与 SDK开发文档
Android App签名打包签名的意义1.为了保证每个程序开发者的合法权益2.放置部分人通过使用相同的Package Name来混淆替换已经安装的程序,从而出现一些恶意篡改3.保证我们每次发布的版本 ...
- 网络虚拟化技术(一): Linux网络虚拟化
创建虚拟网络环境 使用命令 $ ip netns add net0 可以创建一个完全隔离的新网络环境,这个环境包括一个独立的网卡空间,路由表,ARP表,ip地址表,iptables,ebtables, ...