Django(44)drf序列化源码分析(1)
序列化与反序列化
一般后端数据返回给前端的数据格式都是json
格式,简单易懂,但是我们使用的语言本身并不是json
格式,像我们使用的Python
如果直接返回给前端,前端用的javascript
语言是识别不出的,所以我们需要把python
语言转换为通用的json
格式的数据,在django
中就是将orm
模型或者queryset
对象转换成字典,再由字典转换成json
,整个过程就是序列化。
当用户通过在form
表单中填写的数据,发送请求给后端,将数据提交给后端数据库,这个过程就是反序列化。反序列化的时候,我们需要去验证前端提交的数据是否符合后端制定的规范,符合才进行入库。
drf的序列化类
drf
的序列化类有3个
- Serializer
- ModelSerializer(使用最多的)
- ListSerializer
我们使用最多的就是ModelSerializer
,这三个序列化类都继承自BaseSerializer
,虽然我们项目中99%都是使用的ModelSerializer
,但是光知道怎么使用,是没有灵魂的,我们还需要去了解源码,多看源码能迅速提高代码能力。
BaseSerializer
源码分析
源码如下:
class BaseSerializer(Field):
def __init__(self, instance=None, data=empty, **kwargs):
def __new__(cls, *args, **kwargs)
def __class_getitem__(cls, *args, **kwargs)
@classmethod
def many_init(cls, *args, **kwargs):
def to_internal_value(self, data):
def to_representation(self, instance):
def update(self, instance, validated_data):
def create(self, validated_data):
def save(self, **kwargs):
def is_valid(self, raise_exception=False):
@property
def data(self):
@property
def errors(self)
@property
def validated_data(self)
我们分析几个重要的方法,没必要每个方法都了解,分析的都是后面要用到的
__init__方法
def __init__(self, instance=None, data=empty, **kwargs):
self.instance = instance
if data is not empty:
self.initial_data = data
self.partial = kwargs.pop('partial', False)
self._context = kwargs.pop('context', {})
kwargs.pop('many', None)
super().__init__(**kwargs)
初始化方法,有4个参数
- self:本身自己
- instance:实例,默认为
None
- data:数据,默认为
empty
- **kwargs:不定长字典
create
def create(self, validated_data):
raise NotImplementedError('`create()` must be implemented.')
定义了一个create
方法,参数为validated_data
,方法抛出了一个异常,意思是create
方法没有定义,如果要继承BaseSerializer
,那就必须定义create
方法,否则就会抛出异常
update
def update(self, instance, validated_data):
raise NotImplementedError('`update()` must be implemented.')
定义了一个update
方法,有2个参数
instance
:实例,更新数据的时候,需要知道更新的是哪个实例化对象validated_data
:已验证的数据,前端传入的字段需要进行验证
此方法抛出了一个异常,意思是update
方法没有定义,如果要继承BaseSerializer
,那就必须定义update
方法,否则就会抛出异常
is_valid
def is_valid(self, raise_exception=False):
# 如果self对象没有initial_data属性,那么将无法调用该方法,如果需要有initial_data,那么实例化对象必须传入data参数
assert hasattr(self, 'initial_data'), (
'Cannot call `.is_valid()` as no `data=` keyword argument was '
'passed when instantiating the serializer instance.'
)
if not hasattr(self, '_validated_data'):
try:
self._validated_data = self.run_validation(self.initial_data)
except ValidationError as exc:
self._validated_data = {}
self._errors = exc.detail
else:
self._errors = {}
if self._errors and raise_exception:
raise ValidationError(self.errors)
return not bool(self._errors)
这个方法是验证从前端传输过来的字段是否验证成功,如果我们的实例化对象没有传入data
参数,将会无法调用is_valid
,这个方法大多数用在反序列化的时候
save
def save(self, **kwargs):
# 调用save()方法前必须先调用is_valid()
assert hasattr(self, '_errors'), (
'You must call `.is_valid()` before calling `.save()`.'
)
# 不能对无效的数据调用save()方法
assert not self.errors, (
'You cannot call `.save()` on a serializer with invalid data.'
)
# 防止没有正确使用save方法
# Guard against incorrect use of `serializer.save(commit=False)`
assert 'commit' not in kwargs, (
"'commit' is not a valid keyword argument to the 'save()' method. "
"If you need to access data before committing to the database then "
"inspect 'serializer.validated_data' instead. "
"You can also pass additional keyword arguments to 'save()' if you "
"need to set extra attributes on the saved model instance. "
"For example: 'serializer.save(owner=request.user)'.'"
)
# 访问serializer.data后就不能调用save方法了,如果你需要在提交到数据库之前访问数据,那么请使用serializer.validated_data
assert not hasattr(self, '_data'), (
"You cannot call `.save()` after accessing `serializer.data`."
"If you need to access data before committing to the database then "
"inspect 'serializer.validated_data' instead. "
)
# 创建已验证的数据对象
validated_data = {**self.validated_data, **kwargs}
# 如果instance不为空
if self.instance is not None:
# instance对象将更新为validated_data里的内容
self.instance = self.update(self.instance, validated_data)
assert self.instance is not None, (
'`update()` did not return an object instance.'
)
else:
# 如果instance为空,那么则创建对象,对象的内容为validated_data
self.instance = self.create(validated_data)
assert self.instance is not None, (
'`create()` did not return an object instance.'
)
return self.instance
Django(44)drf序列化源码分析(1)的更多相关文章
- 图解Janusgraph系列-图数据底层序列化源码分析(Data Serialize)
图解Janusgraph系列-图数据底层序列化源码分析(Data Serialize) 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 整理所有图相关文章,请移步 ...
- Django(63)drf权限源码分析与自定义权限
前言 上一篇我们分析了认证的源码,一个请求认证通过以后,第二步就是查看权限了,drf默认是允许所有用户访问 权限源码分析 源码入口:APIView.py文件下的initial方法下的check_per ...
- Django之REST framework源码分析
前言: Django REST framework,是1个基于Django搭建 REST风格API的框架: 1.什么是API呢? API就是访问即可获取数据的url地址,下面是一个最简单的 Djang ...
- DRF cbv源码分析 restful规范10条 drf:APIView的源码 Request的源码 postman的安装和使用
CBV 执行流程 路由配置:url(r'^test/',views.Test.as_view()), --> 根据路由匹配,一旦成功,会执行后面函数(request) --> 本质就是执 ...
- Python学习---Django的request.post源码分析
request.post源码分析: 可以看到传递json后会帮我们dumps处理一次最后一字节形式传递过去
- Django rest framework 版本控制(源码分析)
基于上述分析 #2.处理版本信息 处理认证信息 处理权限信息 对用户的访问频率进行限制 self.initial(request, *args, **kwargs) #2.1处理版本信息 #versi ...
- drf认证源码分析
补充: 一.django中间件之路由斜杠的自动添加源码 其实我们每次在写路由的时候,如果在路由层给他设置的是加/,但实际上我们在浏览器中输入的时候并没有加/发现也能调用,前面说了是浏览器内部走了重定向 ...
- Django中间件之SessionMiddleware源码分析
settings.py文件中 MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', ] # from djang ...
- Django _VIEW视图_源码分析
Django _VIEW视图: 1. 点击as_view方法. 第二步: as_view () 为VIEW 类里定义的,到时候我们定义业务逻辑的类就继承这个VIEW类. view方法内返回的是disp ...
随机推荐
- jasypt在springboot项目中遇到异常:Error creating bean with name 'enableEncryptablePropertySourcesPostProcessor' defined in class path resource
背景 在使用jasypt对spring boot的配置文件中的敏感信息进行加密处理时,使用stater直接启动时,遇到了一个异常 <dependency> <groupId>c ...
- python3 mysql API
1. 安装引入 2. 对象简介 3. 代码封装 1. 安装引入 1)安装: pip install PyMySQL 2)Pycharm 中引入 pymysql:
- ES系列(三):网络通信模块解析
ES是一个分布式搜索引擎,其除了用户提供必要的通信服务外,集群间也必须保持紧密的通信联系,才能在必要的时候给出正确的结果.其则必然涉及到各种繁多且要求高的通信场景,那么如何实现高性能的通信,则是其必须 ...
- 写了个简洁的Typora+Markdown简历模板
项目地址:https://github.com/CodingDocs/typora-markdown-resume (欢迎小伙伴们使用!个人能力有限,也欢迎小伙伴们一起完善这个简历模板!). 昨天在 ...
- Vue学习(三)-Vue-router路由的简单使用
一.Vue-Router环境的安装: 如果使用vue-cli脚手架搭建,项目创建过程中会提示你自否选择使用vue-router,选择使用即可, 二.路由学习 1.路由的配置 vue-cli项目自 ...
- SPOJ 2713 线段树(sqrt)
题意: 给你n个数(n <= 100000),然后两种操作,0 x y :把x-y的数全都sqrt ,1 x y:输出 x-y的和. 思路: 直接线段树更新就行了,对于当 ...
- Windows中的共享文件和文件服务器
目录 共享文件的设置 默认共享 关闭默认共享 关闭共享服务 共享文件夹权限 文件服务器资源管理器的搭建 文件共享是指主动地在网络上共享自己的计算机文件.一般文件共享使用P2P模式,文件本身存在用户本人 ...
- UVA11997求前k个和,多路归并问题
题意: 给你一个二维矩阵,n*n的,每次从每一行中拿出来一个,然后加起来组成一个和,一共可以得到n^n个和,要求求出这n^n个和中最小的那n个和. 思路: 多路归并问题,先说下多路 ...
- Windows Pe 第三章 PE头文件(中)
这一章的上半部分大体介绍了下PE文件头,下半部分是详细介绍里面的内容,这一章一定要多读几遍,好好记记基础概念和知识,方便之后的学习. 简单回忆一下: 3.4 PE文件头部解析 3.4.1 DOS M ...
- XCTF-mfw
mfw mfw是什么东西??? 看题: 进来只有几个标签,挨着点一遍,到About页面 看到了Git,猜测有git泄露,访问/.git/HEAD成功 上Githack,但是会一直重复 按了一次ctrl ...