DRF从入门到精通三(反序列化数据校验源码分析、断言Assert、DRF之请求、响应)

文章目录

  • 一、反序列化数据校验源码分析
  • 二、断言Assert
  • 三、DRF之请求、响应
    • Request类和Response类
    • 请求中的Request 能够解析前端传入的编码格式
    • 响应中的Response能够响应的编码格式

一、反序列化数据校验源码分析

反序列化数据校验,校验顺序为:先校验字段自己的规则(最大、最小),然后是局部钩子,然后是全局钩子

  1. 反序列化校验开始
    在视图类中的s_valid()被执行时,就会进行反序列化的校验,校验通过返回True,否则返回False

  2. 反序列化的过程

    • ser.is_valid()是序列化类的对象,假设序列化类是BookSerializer,当执行is_valid时。首先在序列化类产生的对象中查找,当找不到就会去找到它的父类中找,结果在它父类的父类中找到了BaseSerializer
	BaseSerializer类def is_valid(self, *, raise_exception=False):'断言检查,确保类的实例中具有名为initial_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'):'''self序列化类的对象,属性中没有_validated_data,就一定会走这句并且只要走过一次后,下一次就无需再次走了,它优化了is_valid被多次调用,只会走一次校验'''try:'真正的走校验,一旦执行了这里,以后self中就有了_validated_data''''然后我们就得去看看这个self.run_validation(self.initial_data)我们不能直接按住ctrl键点击,因为它会从当前类中找run_validation,我们得清楚,这个self是谁,它还是我们的视图类,所以我们得返回到视图类从它一步一步往它继承的类中找清楚如何查找后,我们就从视图类----》serializer.Serializer(找到了,为什么从这个里面找因为我们就是使用serializer.Serializer类的)'''self._validated_data = self.run_validation(self.initial_data)'''这下面的是当校验不通过时,执行的,会给_validatad_data设置为一个空字段,并且给_errors设置为验证错误的详细信息'''except ValidationError as exc:self._validated_data = {}self._errors = exc.detailelse:self._errors = {}return not bool(self._errors)通过上面self.run_validation(self.initial_data)我们找到了下面这块源码,而这里的run_validatiion方法就是DRF序列化器验证过程中的核心def run_validation(self, data=empty):'''局部钩子的执行,这里的self就还是视图类的对象data就是前端传入的数据,value是前端传入,字段自己校验通过的字典'''value = self.to_internal_value(data)try:'这个是字段验证器'self.run_validators(value)'''这个是全局钩子的执行,和上面一样self是视图类的对象,如果我们在序列化其中写了全局钩子,那么就优先使用我们自己定义的全局钩子,如果没写则执行父类的,(serializer.Serializer)结果可以看到父类根本就没有做校验def validate(self, attrs):return attrs'''value = self.validate(value)  #运行自定义验证方法'确保自定义验证方法返回了验证后的数据'assert value is not None, '.validate() should return the validated data'except (ValidationError, DjangoValidationError) as exc:# 捕获验证过程中可能引发的异常,并转换为DRF的ValidationErrorraise ValidationError(detail=as_serializer_error(exc))# 返回验证后的数据return value看完了全局钩子后我们在看一下局部钩子的self.to_internal_value(data),也是一样的思路,从视图类找,视图类肯定没有,然后找父类serializer结果就是这个页面的def to_internal_value(self, data):ret = OrderedDict()# 用于存储验证后的数据errors = OrderedDict()# 用于存储字段验证过程中的错误信息fields = self._writable_fields# 获取序列化器中的所有字段'序列化类中所有的字段,for循环每次取一个字段对象。例如name=CharField()'for field in fields: '''去视图类的对象中反射,validate_字段名的方法,如果有就执行,没有就不执行'''validate_method = getattr(self, 'validate_' + field.field_name, None)primitive_value = field.get_value(data)try:'这句话就是字段自己的校验规则(最长最短长度等)'validated_value = field.run_validation(primitive_value)'局部钩子,如果在序列化类中写了局部钩子验证规则,就运行自己写的'if validate_method is not None:'执行局部钩子,传入当前字段的value值'validated_value = validate_method(validated_value)'如果抛异常了就会被捕获'except ValidationError as exc:'捕获DRF的ValidationError异常'errors[field.field_name] = exc.detailexcept DjangoValidationError as exc:'捕获Django的ValidationError异常'errors[field.field_name] = get_error_detail(exc)except SkipField:'如果遇到SkipField异常,就跳过该字段的处理'passelse:'如果没有异常,将验证后的值设置到结果中'set_value(ret, field.source_attrs, validated_value)if errors:raise ValidationError(errors)return ret

这里提一下如何追源码,查看下面两张图即可。
在这里插入图片描述
在这里插入图片描述

二、断言Assert

	'''普通写法'''name = 'jack1'if not name == 'jack':raise Exception('name不登录jack')'''断言写法''''assert 后写条件,只要不符合条件,就会跑AssertionErro异常,后面写异常信息'name = 'tom'assert name == 'tom','name不是tom'print('程序执行完毕!')'源码中使用'assert value is not None, '.validate() should return the validated data'

三、DRF之请求、响应

Request类和Response类

Request类

REST FrameWork传入视图的Request对象不再是Django默认的HttpRequest对象
而是REST FrameWork提供的扩展了HttpResponse类的Request类的对象了
Rest FrameWork提供了Parser解析器 在接收到请求后自动根据Content-type指明的数据类型(默认是JSON)
将请求数据进行Parse解析 解析为字典[QueryDict]对象保存到Request对象
Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果
无论前端发送的哪种格式数据 我们都可以用同一个一种方式读取数据

属性data
request.data返回解析之后的请求题数据 类似于Django中的request.POSTrequest.FILES属性

  • 包含了解析之后的文件和非文件数据
  • 包含了对POST、PUT、PATCH请求方式解析后的数据
  • 利用了REST FrameWork的Parsers解析器 不仅仅支持表单类型数据 也支持JSON数据

属性query_params
request.query_params与Django标准的request.GET相同 只是更换了更正确的名称


Response类

	Response(data=None, status=None,template_name=None, headers=None,exception=False, content_type=None)

REST FrameFork提供了一个响应类Response使用该类构造响应对象时 响应的具体数据内容会被转换(render渲染)成符合前端需求的类型
REST FrameFork提供了Renderer渲染器 用来根据请求投中的Accept接收数据类型声明 来自动转换响应数据到对应格式 如果前端请求中未进行Accept声明 则会采用默认方式处理响应数据
我们可以通过配置来修改默认响应格式 可以在rest_framework.settings查找所有的drf默认配置项

	REST_FRAMEWORK = {'DEFAULT_RENDERER_CLASSES': (   # 默认响应渲染类'rest_framework.renderers.JSONRenderer',    # JSON渲染器'rest_framework.renderers.BrowsableAPIRenderer',    # 浏览器API渲染器)}

参数说明:

  • data 为响应准备的序列化处理后的数据
  • status 状态码默认200
  • template_name 模版名称 如果使用HTML Renderer时需要指定
  • headers 用于存放响应头信息的字典
  • content_type 响应数据的Content_type 通常此参数无需传递 REST FrameWork会根据前端所需类型数据来设置该参数

常用属性

  • data 传给response对象的序列化后 但还没有给render处理的数据
  • status_code 状态码数字
  • content 经过render处理后的响应数据

状态码
为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量。
1)信息告知 - 1xx

	HTTP_100_CONTINUEHTTP_101_SWITCHING_PROTOCOLS

2)成功 - 2xx

	HTTP_200_OKHTTP_201_CREATEDHTTP_202_ACCEPTEDHTTP_203_NON_AUTHORITATIVE_INFORMATIONHTTP_204_NO_CONTENTHTTP_205_RESET_CONTENTHTTP_206_PARTIAL_CONTENTHTTP_207_MULTI_STATUS

3)重定向 - 3xx

	HTTP_300_MULTIPLE_CHOICESHTTP_301_MOVED_PERMANENTLYHTTP_302_FOUNDHTTP_303_SEE_OTHERHTTP_304_NOT_MODIFIEDHTTP_305_USE_PROXYHTTP_306_RESERVEDHTTP_307_TEMPORARY_REDIRECT

4)客户端错误 - 4xx

	HTTP_400_BAD_REQUESTHTTP_401_UNAUTHORIZEDHTTP_402_PAYMENT_REQUIREDHTTP_403_FORBIDDENHTTP_404_NOT_FOUNDHTTP_405_METHOD_NOT_ALLOWEDHTTP_406_NOT_ACCEPTABLEHTTP_407_PROXY_AUTHENTICATION_REQUIREDHTTP_408_REQUEST_TIMEOUTHTTP_409_CONFLICTHTTP_410_GONEHTTP_411_LENGTH_REQUIREDHTTP_412_PRECONDITION_FAILEDHTTP_413_REQUEST_ENTITY_TOO_LARGEHTTP_414_REQUEST_URI_TOO_LONGHTTP_415_UNSUPPORTED_MEDIA_TYPEHTTP_416_REQUESTED_RANGE_NOT_SATISFIABLEHTTP_417_EXPECTATION_FAILEDHTTP_422_UNPROCESSABLE_ENTITYHTTP_423_LOCKEDHTTP_424_FAILED_DEPENDENCYHTTP_428_PRECONDITION_REQUIREDHTTP_429_TOO_MANY_REQUESTSHTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGEHTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS

5)服务器错误 - 5xx

	HTTP_500_INTERNAL_SERVER_ERRORHTTP_501_NOT_IMPLEMENTEDHTTP_502_BAD_GATEWAYHTTP_503_SERVICE_UNAVAILABLEHTTP_504_GATEWAY_TIMEOUTHTTP_505_HTTP_VERSION_NOT_SUPPORTEDHTTP_507_INSUFFICIENT_STORAGEHTTP_511_NETWORK_AUTHENTICATION_REQUIRED

请求中的Request 能够解析前端传入的编码格式

方式一 局部配置

在继承APIView及其子类的的视图类中配置

	from rest_framework.parsers import JSONParser,FormParser,MultiPartParserclass BookView(APIView):parser_classes = [JSONParser,]

方式二全局配置
在配置文件中配置(影响所有,全局配置)

  • django项目有默认配置,每个项目有独立的一个配置文件
	from django.conf import settingsfrom djangoday01 import settings
  • drf有默认配置,每个项目有独立的一个配置文件---->>>django的配置文件中
	from rest_framework import settingsfrom drf_day05 import settingsREST_FRAMEWORK = {'DEFAULT_PARSER_CLASSES': ['rest_framework.parsers.JSONParser',  # 默认json默认'rest_framework.parsers.FormParser',  # 默认urlencoded编码'rest_framework.parsers.MultiPartParser', # 默认form_data编码],}

方式三

如果全局配了1个,某个视图类想要3个,如何配置?

  1. 全局配置不用动,只需要在视图类中配置能够解析前端数据的3种编码格式
  2. 视图类中,查询的顺序:视图类自身——>项目drf配置——>drf默认配置

响应中的Response能够响应的编码格式

方式一
在视图类中写-----局部配置

	# 响应格式from rest_framework.renderers import JSONRenderer,BrowsableAPIRendererclass BookView(APIView):renderer_classes=[JSONRenderer,]

方式二
在项目配置文件中写—全局配置

	REST_FRAMEWORK = {'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer',],}

方式三

使用顺序(一般就用内置的即可)。使用顺序:视图类自身配置——>项目drf配置——>drf默认内置的配置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/240504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go后端开发 -- Golang的语言特性

Go后端开发 – Golang的语言特性 文章目录 Go后端开发 -- Golang的语言特性一、Golang的优势1.部署极其简单:2.静态语言3.语言层面的并发4.强大的标准库5.简单易学6.运行效率对比 二、Golang的适用领域1.应用领域2.明星产品 三、Golang的不足 一、Golang的优势 1.部…

共享购:消费前沿的领导者

在当今这个信息化、互联网高速发展的时代,商业模式也在不断地创新和变革。共享购模式作为一种新型的商业模式,正逐渐受到广泛的关注和追捧。本文将深入探讨共享购模式的核心理念、优势以及如何应用在实际商业场景中,为读者揭示这一模式的巨大…

计算机组成原理综合5

A 按照题意,程序P执行的时钟周期数为1000080%11000020%1028000,程序P的平均CPI为28000/100002.8,计算机主频为1GHz,CPU执行时间为28000/(1G/s)28μs。 B A 符号位为1 首先将0.4375转化为二进制,0.250.1250.06250.43…

nodejs+vue+ElementUi资源互助共享平台的设计

后台:管理员功能有个人中心,用户管理,卖家管理,咨询师管理,萌宝信息管理,幼儿知识管理,保姆推荐管理,音频资源管理,二手商品管理,商品分类管理,资…

推荐给前端开发的 5 款 Chrome 扩展

工欲善其事,必先利其器。Chrome 可能是前端开发中使用最多的浏览器。在日常开发中,下列几款 Chrome 扩展也许能让你的开发工作事半功倍 🚀 Vue.js devtools ⚙️ vue 官方专为 vue 应用开发的调试工具。 通过使用它,你可以快速查看…

力扣单调栈算法专题训练

目录 1 专题说明2 训练 1 专题说明 本博客用来计算力扣上的单调栈题目、解题思路和代码。 单调栈题目记录: 2232866美丽塔II 2 训练 题目1:2866美丽塔II。 解题思路:先计算出prefix[i],表示0~i满足递增情况下,0~i…

NC65 查询单据所处的流程状态以及流程平台客户端工具类

1、查询单据所处的流程状态 nc.bs.wfengine.engine.EngineService的queryFlowStatus()方法 /*** 查询单据所处的流程状态* * param billId* param billType* param result* return* throws DbException*/public int queryFlowStatus(String billId, String billType, int flo…

【UML】第8篇 用例图(3/3)

目录 一、用例的关系 1.1 泛化(Generalization)关系 1.2 包含(include)关系 1.3 扩展关系 二、用例表示例 不是非要把电影改成连续剧,给大家播,确实是时间和精力有限。 用例图,虽然简单&…

荣誉 | 第七在线(7thonline)荣获STIF2023年度数智化创新典范奖

12月15日,STIF2023 第四届国际科创节暨 DSC2023 国际数字服务大会(数服会)在北京隆重举行。 在本届科创节暨数服会活动评选中,经企业申报、评委会审议,第七在线(7thonline)AI智能零售商品计划库…

什么是集成测试?它和系统测试的区别是什么? 操作方法来了

01 什么是集成测试? 集成测试是软件测试的一种方法,用于测试不同的软件模块之间的交互和协作是否正常。集成测试的主要目的是确保不同的软件模块能够无缝协作,形成一个完整的软件系统,并且能够满足系统的需求和规格。 在集成测试…

【3D生成与重建】SSDNeRF:单阶段Diffusion NeRF的三维生成和重建

系列文章目录 题目:Single-Stage Diffusion NeRF: A Unified Approach to 3D Generation and Reconstruction 论文:https://arxiv.org/pdf/2304.06714.pdf 任务:无条件3D生成(如从噪音中,生成不同的车等)、…

[C++]模板进阶

目录 C模板进阶:: 非类型模板参数 模板的特化 函数模板特化 类模板特化 全特化 偏特化 模板的分离编译 模板总结 C模板进阶:: 非类型模板参数 模板参数可分为类型形参和非类型形参。 类型形参:出现在参数列表中&am…

浅谈Redis分布式锁(上)

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 不论面试还是实际工作中…

信息安全等级保护的定义与意义

目录 前言 信息安全等级保护定义 广义上 狭义上 技术和管理 信息安全的基本要素 信息安全等级保护的意义 当前形式 形式严峻 国家安全 三个基本一个根本 预期目标 最终效果 实际意义 前言 信息安全等级保护是对信息和信息载体按照重要性等级分级进行保护的一种…

Windows平台开发需要掌握的基础知识

windows本身也是一个软件。在这个软件中进行开发时,我们需要对它有个基础的了解,这样能让我们的开发过程更顺畅一些。 下面我就来说一下我们需要关注的基础知识点。 环境变量 有时候我们的程序执行,需要基于一些基础的库。比如Java运行&am…

matlab 最小二乘拟合平面(直接求解法)

目录 一、算法原理二、代码实现三、算法效果本文由CSDN点云侠原创,原文链接。爬虫网站自重。 一、算法原理 平面方程的一般表达式为: A x + B y +

【Skynet 入门实战练习】事件模块 | 批处理模块 | GM 指令 | 模糊搜索

文章目录 前言事件模块批处理模块GM 指令模块模糊搜索最后 前言 本节完善了项目,实现了事件、批处理、模糊搜索模块、GM 指令模块。 事件模块 什么是事件模块?事件模块是用来在各系统之间传递事件消息的。 为什么需要事件模块?主要目的是…

Spring源码分析 @Autowired 是怎样完成注入的?究竟是byType还是byName亦两者皆有

1. 五种不同场景下 Autowired 的使用 第一种情况 上下文中只有一个同类型的bean 配置类 package org.example.bean;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class FruitCo…

推箱子小游戏

--print("开发流程步骤:I、绘制推箱子地图并初始化 ----- 几*几大小的地图 \n\n II、根据宏定义和推箱子地图上的数字来选择不同的图形\n\n III、获取玩家坐标 -----------重点\n\n …

html旋转相册

一、实验题目 做一个旋转的3d相册 二、实验代码 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport&qu…