反序列化类校验部分源码解析

# 反序列化校验,什么时候开始执行校验
视图类中的ser.is_valid(),就会执行校验,校验通过返回True,不通过返回false
# 反序列化类校验的入口: ser.is_valid()
ser.is_valid()是序列化类的对象,假设序列化类是BookSerializer
---》is_valid---》找不到,找到父类BaseSerializer中有 :【 raise_exception:先注意】
def is_valid(self, *, raise_exception=False): if not hasattr(self, '_validated_data'):
try:
# self序列化类的对象,属性中没有_validated_data,一定会走这句【核心】
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)
# self._validated_data = self.run_validation(self.initial_data) 核心--》self序列化类的对象
-切记一定不要按住ctrl键点击
-真正的执行顺序是,从下往上找,找不到,再往上
-最终从Serializer类中找到了run_validation,而不是Field中的run_validation def run_validation(self, data=empty):
# 字段自己的,validates方法
(is_empty_value, data) = self.validate_empty_values(data)
if is_empty_value:
return data
# 局部钩子----【局部钩子】
value = self.to_internal_value(data)
try: self.run_validators(value)
# 全局钩子--》如果在BookSerializer中写了validate,优先走它,非常简单
value = self.validate(value) except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc)) return value # 局部钩子 self.to_internal_value(data) ---》self是BookSerializer的对象,从根上找
def to_internal_value(self, data):
ret = OrderedDict()
errors = OrderedDict()
fields = self._writable_fields
# fields写在序列化类中一个个字段类的对象
for field in fields:
# self BookSerializer的对象,反射validate_name
validate_method = getattr(self, 'validate_' + field.field_name, None)
try:
# 在执行BookSerializer类中的validate_name方法,传入了要校验的数据
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail else:
set_value(ret, field.source_attrs, validated_value) if errors:
raise ValidationError(errors) return ret

断言

# 断言的关键字
assert : 断定你是XX,如果不是就抛异常
# 源码中大量使用了try和断言
# 断言的使用
name = 'tom'

# if name = 'tom':
# print('对')
# else:
# raise Exception('名字不能是tom以外的') assert name='tom' # 断定是,不是直接抛异常
print('名字不能是tom以外的')

drf之请求

# 1.Request能够解析的前端传入的编码格式

# 方式一:继承来自APIView及其子类的视图类中配置(局部配置)
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
# 我们所写的接口,只能接收某种编码格式,比如接收json格式
# parser_classes:解析类,意思是能够解析前端传入的什么编码格式[默认情况配了三个解析类,现在只需要配一个解析类]
parser_classes = [JSONParser,] def post(self, request):
# 请求中携带数据,都从request.data中取
print(request.data)
# 如果是json格式编码,request.data就是普通dict
# 如果是urlencoded,form-data格式编码,request.data就是普通django.http.request.QueryDict
print(type(request.data))
return Response() # 方式二:直接在配置文件中配置(影响所有,全局配置)
- django有套默认配置,每个项目有个配置
- drf有套默认配置,在django的配置文件中:
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
# 'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
# 'rest_framework.parsers.MultiPartParser',
],
} # 方式三:全局配了一个,某个视图类需要三个,如何配置:
- 只需要在视图类,配置三个即可
- 因为:先从视图类自身找,找不到需要去项目drf配置中找,最后去drf默认配置中找


# 2.Request类有哪些属性和方法
- 视图类方法中的request
data
__getattr__
query_params

drf之响应

# drf 是django的一个app,所以要注册
# drf的响应,如果使用浏览器和postman访问,返回的格式不同
- 原因是drf做了判断,对于浏览器会返回好看一些,对于postman只会返回json数据 # 方式一:在视图类中写(局部配置)
- 两个响应类--->在drf配置文件中找--->两个类
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookView(APIView):
# 我们所写的接口,只能接收某种编码格式,比如接收json格式
# parser_classes:解析类,意思是能够解析前端传入的什么编码格式[默认情况配了三个解析类,现在只需要配一个解析类]
# parser_classes = [JSONParser,] renderer_classes = [JSONRenderer,]
def post(self, request):
# 请求中携带数据,都从request.data中取
print(request.data)
# 如果是json格式编码,request.data就是普通dict
# 如果是urlencoded,form-data格式编码,request.data就是普通django.http.request.QueryDict
print(type(request.data))
return Response() # 方式二:在项目配置文件中写(全局配置)
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
} # 方式三:使用顺序(一般使用内置的就行)
优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的配置 # Response源码属性和方法
- drf源码分析
from rest_framework.response import Response
- 视图类的方法返回时,return Response, 走自己的__init__,
init中可以传入的参数有:
def __init__(self,
data=None,
status=None,
template_name=None,
headers=None,
exception=False,
content_type=None)
data:
1. 之前写的ser.data 可以是字典或列表,字符串
2. 序列化之后返回给前端
3.前端在响应体代码中看到的就是这个data status:
1.http响应的状态码,默认是200,可以改
2.drf在status包下,把所有http响应状态码都写一遍
3.from rest_framework.status import HTTP_200_OK
4.Response('dddd',status=status.HTTP_200_OK)
template_name:
了解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子
headers:
响应头,http响应头,如何在响应头中加东西
content_type :
响应编码格式,一般不动 """
重点:data,status,headers
"""

视图组件介绍及两个视图基类

# drf视图类
# 1.APIVIew跟之前View区别
- 传入到视图方法中的是REST framework和Request对象,而不是Django的HttpRequest对象:
- 视图方法可以返回 REST framework的Response对象
- 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
- 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制 # 2.两个视图基类
- APIView
-类属性:
renderer_classes # 响应格式
parser_classes #能够解析的请求格式
authentication_classes #认证类
throttle_classes #频率类
permission_classes #权限类
-基于APIView+ModelSerializer+Resposne写5个接口
详见代码 # 3.视图类
from .models import Book
from .serializer import BookSerializer class BookView(APIView):
def get(self, request):
books = Book.objects.all()
ser = BookSerializer(instance=books, many=True)
return Response(ser.data) def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
# 咱们现在只有ser序列化类的对象,但是咱们想要,新增的对象---》序列化成字典---》大前提,序列化类中的create方法一定要返回新增的对象
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors}) class BookDetailView(APIView):
def get(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books)
return Response(ser.data) def put(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors}) def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'}) # 4.序列化类
### ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
# 跟表有关联
class Meta:
model = Book
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
} # 5.路由
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
path('books/<int:pk>/', views.BookDetailView.as_view()),
]

基于GenericAPIView+5个视图扩展类

# 1.视图类
from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, \
ListModelMixin # 基于GenericAPIView+5个视图扩展类写接口 class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request):
return self.list(request) def post(self, request):
return self.create(request) class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs) def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs) # 2.序列化类
class BookSerializer(serializers.ModelSerializer):
# 跟表有关联
class Meta:
model = Book
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
} # 3.路由
class BookSerializer(serializers.ModelSerializer):
# 跟表有关联
class Meta:
model = Book
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}

drf从入门到飞升仙界 05的更多相关文章

  1. 【Lucene3.6.2入门系列】第05节_自定义停用词分词器和同义词分词器

    首先是用于显示分词信息的HelloCustomAnalyzer.java package com.jadyer.lucene; import java.io.IOException; import j ...

  2. Docker从入门到飞升:基础配置安装

    导读 Docker近几年非常火,因为它是容器虚拟化,更能够充分提高硬件资源的使用率.其实利用率高不算什么,它最大的优势是能给让运维人员或者开发人员快速部署和交付资源,大大提高了工作效率.几乎所有的大企 ...

  3. Linux性能优化从入门到实战:05 CPU篇:硬中断、软中断

      软中断(softirq)会导致CPU 使用率升高   中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求.中断其实是一种异步的事件 ...

  4. 爬虫入门到放弃系列05:从程序模块设计到代理IP池

    前言 上篇文章吧啦吧啦讲了一些有的没的,现在还是回到主题写点技术相关的.本篇文章作为基础爬虫知识的最后一篇,将以爬虫程序的模块设计来完结. 在我漫(liang)长(nian)的爬虫开发生涯中,我通常将 ...

  5. opengl入门学习

    OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...

  6. 廖雪峰Git入门教程

    廖雪峰Git入门教程  2018-05-24 23:05:11     0     0     0 https://www.liaoxuefeng.com/wiki/00137395163059296 ...

  7. php从入门到放弃系列-01.php环境的搭建

    php从入门到放弃系列-01.php环境的搭建 一.为什么要学习php 1.php语言适用于中小型网站的快速开发: 2.并且有非常成熟的开源框架,例如yii,thinkphp等: 3.几乎全部的CMS ...

  8. OpenGL入门学习(转载)

    说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色 ...

  9. drf源码剖析系列(系列目录)

    drf源码剖析系列(系列目录) 01 drf源码剖析之restful规范 02 drf源码剖析之快速了解drf 03 drf源码剖析之视图 04 drf源码剖析之版本 05 drf源码剖析之认证 06 ...

  10. Python学习从入门到放弃?我不允许!!!

    嗨,大家好 这里是汐仔 很多人都说学习python学习python,打开书本,三分钟,从入门到放弃. 这怎么可以!!!大家能选择python的原因可能是看它既简单,好入门,现在俨然是语言中的一匹黑马. ...

随机推荐

  1. R.swift 使用详解

    R.Swift 能快速访问本地图片.颜色.字体等资源的一个库 使用介绍 1.工程中倒入R.swift 以pod为例 pod 'R.swift' 2.配置执行脚本 "$PODS_ROOT/R. ...

  2. 蓝牙mesh组网实践(环境监测传感器应用)

    目录 蓝牙mesh组网中的低功耗节点,在应用于低频率上传数据的传感器网络时有着得天独厚的功耗优势,在1min唤醒上传一包的情况下ch582的平均功耗仅有12uA,若每小时甚至每天采样一次数据并上传,平 ...

  3. CSS实现开门效果

    .door{ position: relative; width: 450px; height: 300px; border: 1px solid #000; margin: 100px auto; ...

  4. PDF.JS 预览pdf文件,中文不显示问题

    pdf.js 下载路径 http://mozilla.github.io/pdf.js/ pdf.js的使用不多说,网上都有 讲一下,.NET CORE MVC的使用遇到的问题 1. 将下载文件解压放 ...

  5. Sql Sugar 使用

    sql sugar orm文档地址: SqlSugar ORM 5.X 官网 .文档.教程 - SqlSugar 5x - .NET果糖网 (donet5.com) sql sugar 基本用法大全, ...

  6. python运行脚本报错Non-UTF-8

    写完脚本运行报:SyntaxError: Non-UTF-8 code starting with '\xa1' in file/createuser/test.py on line 1, but n ...

  7. python 的多线程

    创建一个多线程 from threading import Thread, ThreadError import time def task_01(): print("开始发送邮件" ...

  8. 转载-Shell脚本中字符串截取功能

    在Shell脚本编写中,有几个地方都是要用到字符串截取的功能,那将这块的内容进行下记录: 1.字符串变量的截取操作 对字符串变量的截取操作一般都是通过${操作符}的方式进行 1)从指定位置index截 ...

  9. vue 中的 provide/inject

    provide/inject 是 vue 2.2.0 版本新增 类型: provide:Object | () => Object inject:Array<string> | { ...

  10. 分布式锁 -- redis

    原理 redis设置一个key和value,如果存在则获取锁失败,不存在则获取锁成功处理业务,业务处理完成后删除这条数据,可以带个失效时间. 代码 public void handleInvoice( ...