序列化与反序列化

  一般后端数据返回给前端的数据格式都是json格式,简单易懂,但是我们使用的语言本身并不是json格式,像我们使用的Python如果直接返回给前端,前端用的javascript语言是识别不出的,所以我们需要把python语言转换为通用的json格式的数据,在django中就是将orm模型或者queryset对象转换成字典,再由字典转换成json,整个过程就是序列化。

  当用户通过在form表单中填写的数据,发送请求给后端,将数据提交给后端数据库,这个过程就是反序列化。反序列化的时候,我们需要去验证前端提交的数据是否符合后端制定的规范,符合才进行入库。

drf的序列化类

drf的序列化类有3个

  • Serializer
  • ModelSerializer(使用最多的)
  • ListSerializer

我们使用最多的就是ModelSerializer,这三个序列化类都继承自BaseSerializer,虽然我们项目中99%都是使用的ModelSerializer,但是光知道怎么使用,是没有灵魂的,我们还需要去了解源码,多看源码能迅速提高代码能力。

BaseSerializer源码分析

源码如下:

  1. class BaseSerializer(Field):
  2. def __init__(self, instance=None, data=empty, **kwargs):
  3. def __new__(cls, *args, **kwargs)
  4. def __class_getitem__(cls, *args, **kwargs)
  5. @classmethod
  6. def many_init(cls, *args, **kwargs):
  7. def to_internal_value(self, data):
  8. def to_representation(self, instance):
  9. def update(self, instance, validated_data):
  10. def create(self, validated_data):
  11. def save(self, **kwargs):
  12. def is_valid(self, raise_exception=False):
  13. @property
  14. def data(self):
  15. @property
  16. def errors(self)
  17. @property
  18. def validated_data(self)

我们分析几个重要的方法,没必要每个方法都了解,分析的都是后面要用到的

__init__方法

  1. def __init__(self, instance=None, data=empty, **kwargs):
  2. self.instance = instance
  3. if data is not empty:
  4. self.initial_data = data
  5. self.partial = kwargs.pop('partial', False)
  6. self._context = kwargs.pop('context', {})
  7. kwargs.pop('many', None)
  8. super().__init__(**kwargs)

初始化方法,有4个参数

  • self:本身自己
  • instance:实例,默认为None
  • data:数据,默认为empty
  • **kwargs:不定长字典

create

  1. def create(self, validated_data):
  2. raise NotImplementedError('`create()` must be implemented.')

定义了一个create方法,参数为validated_data,方法抛出了一个异常,意思是create方法没有定义,如果要继承BaseSerializer,那就必须定义create方法,否则就会抛出异常

update

  1. def update(self, instance, validated_data):
  2. raise NotImplementedError('`update()` must be implemented.')

定义了一个update方法,有2个参数

  • instance:实例,更新数据的时候,需要知道更新的是哪个实例化对象
  • validated_data:已验证的数据,前端传入的字段需要进行验证

此方法抛出了一个异常,意思是update方法没有定义,如果要继承BaseSerializer,那就必须定义update方法,否则就会抛出异常

is_valid

  1. def is_valid(self, raise_exception=False):
  2. # 如果self对象没有initial_data属性,那么将无法调用该方法,如果需要有initial_data,那么实例化对象必须传入data参数
  3. assert hasattr(self, 'initial_data'), (
  4. 'Cannot call `.is_valid()` as no `data=` keyword argument was '
  5. 'passed when instantiating the serializer instance.'
  6. )
  7. if not hasattr(self, '_validated_data'):
  8. try:
  9. self._validated_data = self.run_validation(self.initial_data)
  10. except ValidationError as exc:
  11. self._validated_data = {}
  12. self._errors = exc.detail
  13. else:
  14. self._errors = {}
  15. if self._errors and raise_exception:
  16. raise ValidationError(self.errors)
  17. return not bool(self._errors)

这个方法是验证从前端传输过来的字段是否验证成功,如果我们的实例化对象没有传入data参数,将会无法调用is_valid,这个方法大多数用在反序列化的时候

save

  1. def save(self, **kwargs):
  2. # 调用save()方法前必须先调用is_valid()
  3. assert hasattr(self, '_errors'), (
  4. 'You must call `.is_valid()` before calling `.save()`.'
  5. )
  6. # 不能对无效的数据调用save()方法
  7. assert not self.errors, (
  8. 'You cannot call `.save()` on a serializer with invalid data.'
  9. )
  10. # 防止没有正确使用save方法
  11. # Guard against incorrect use of `serializer.save(commit=False)`
  12. assert 'commit' not in kwargs, (
  13. "'commit' is not a valid keyword argument to the 'save()' method. "
  14. "If you need to access data before committing to the database then "
  15. "inspect 'serializer.validated_data' instead. "
  16. "You can also pass additional keyword arguments to 'save()' if you "
  17. "need to set extra attributes on the saved model instance. "
  18. "For example: 'serializer.save(owner=request.user)'.'"
  19. )
  20. # 访问serializer.data后就不能调用save方法了,如果你需要在提交到数据库之前访问数据,那么请使用serializer.validated_data
  21. assert not hasattr(self, '_data'), (
  22. "You cannot call `.save()` after accessing `serializer.data`."
  23. "If you need to access data before committing to the database then "
  24. "inspect 'serializer.validated_data' instead. "
  25. )
  26. # 创建已验证的数据对象
  27. validated_data = {**self.validated_data, **kwargs}
  28. # 如果instance不为空
  29. if self.instance is not None:
  30. # instance对象将更新为validated_data里的内容
  31. self.instance = self.update(self.instance, validated_data)
  32. assert self.instance is not None, (
  33. '`update()` did not return an object instance.'
  34. )
  35. else:
  36. # 如果instance为空,那么则创建对象,对象的内容为validated_data
  37. self.instance = self.create(validated_data)
  38. assert self.instance is not None, (
  39. '`create()` did not return an object instance.'
  40. )
  41. return self.instance

Django(44)drf序列化源码分析(1)的更多相关文章

  1. 图解Janusgraph系列-图数据底层序列化源码分析(Data Serialize)

    图解Janusgraph系列-图数据底层序列化源码分析(Data Serialize) 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 图数据库文章总目录: 整理所有图相关文章,请移步 ...

  2. Django(63)drf权限源码分析与自定义权限

    前言 上一篇我们分析了认证的源码,一个请求认证通过以后,第二步就是查看权限了,drf默认是允许所有用户访问 权限源码分析 源码入口:APIView.py文件下的initial方法下的check_per ...

  3. Django之REST framework源码分析

    前言: Django REST framework,是1个基于Django搭建 REST风格API的框架: 1.什么是API呢? API就是访问即可获取数据的url地址,下面是一个最简单的 Djang ...

  4. DRF cbv源码分析 restful规范10条 drf:APIView的源码 Request的源码 postman的安装和使用

    CBV 执行流程 路由配置:url(r'^test/',views.Test.as_view()),  --> 根据路由匹配,一旦成功,会执行后面函数(request) --> 本质就是执 ...

  5. Python学习---Django的request.post源码分析

    request.post源码分析: 可以看到传递json后会帮我们dumps处理一次最后一字节形式传递过去

  6. Django rest framework 版本控制(源码分析)

    基于上述分析 #2.处理版本信息 处理认证信息 处理权限信息 对用户的访问频率进行限制 self.initial(request, *args, **kwargs) #2.1处理版本信息 #versi ...

  7. drf认证源码分析

    补充: 一.django中间件之路由斜杠的自动添加源码 其实我们每次在写路由的时候,如果在路由层给他设置的是加/,但实际上我们在浏览器中输入的时候并没有加/发现也能调用,前面说了是浏览器内部走了重定向 ...

  8. Django中间件之SessionMiddleware源码分析

    settings.py文件中 MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', ] # from djang ...

  9. Django _VIEW视图_源码分析

    Django _VIEW视图: 1. 点击as_view方法. 第二步: as_view () 为VIEW 类里定义的,到时候我们定义业务逻辑的类就继承这个VIEW类. view方法内返回的是disp ...

随机推荐

  1. Day03_16_递归

    Java递归 递归包含两个部分 递归头: 标明了什么时候结束递归调用,如果没有递归头,程序将陷入死循环. 递归体: 标明了什么时候需要继续调用自身. 实例 import java.util.Scann ...

  2. Nginx 配置浏览Linux 系统目录并下载文件

    准备工作: 安装编译工具及库文件: yum -y install make zlib zlib-devel gcc-c++ libtool  openssl openssl-devel 安装PCRE( ...

  3. 【ElasticSearch】shards,replica,index之间的关系

    1.index 包含多个shard ,在创建index的时候可以自定义shards和replica的数量 例如: 新增一个index,手动指定shard和replica的数量 PUT demo_ind ...

  4. android so加载

    本文分析so加载的步骤,其实在之前dalvik浅析二中也有提及,但那重点关注的是jni.android中so库的加载,代码如下: loadLibrary("nanosleep"); ...

  5. CVE-2013-0077:Microsoft DirectShow quartz.dll m2p 文件堆溢出漏洞简单分析

    0x01 前言 2012 年 10 月 5 日,exploit-db 漏洞公布站点上发布了 QQplayer.exe 3.7.892 m2p quartz.dll Heap Pointer OverW ...

  6. c#-全局键盘钩子

    using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using ...

  7. (2) arm 指令条件码

    条件码助记符 标志 含义 EQ Z=1 相等 NE Z=0 不相等 CS/HS C=1 无符号数大于或等于 CC/LO C=0 无符号数小于 MI N=1 负数 PL N=0 正数或0 VS V=1 ...

  8. ATK&CK红队评估实战靶场 (一)的搭建和模拟攻击过程全过程

    介绍及环境搭建 靶机地址:http://vulnstack.qiyuanxuetang.net/vuln/detail/2 官方靶机说明: 红队实战系列,主要以真实企业环境为实例搭建一系列靶场,通过练 ...

  9. 1、requests基础

    一.升级pip版本的命令 : python -m pip install --upgrade pip 二.requests安装  windows系统系cmd运行 pip install request ...

  10. nginx 配置后页面访问是报500错

    该问题是html文件权限问题. 用jenkins 并远程服务器上传到另一台服务器的html ,在配置好nginx 的location  root 绝对位置后还是报错500 手工用root上传时访问正常 ...