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

# 反序列化校验,什么时候开始执行校验
视图类中的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. Delete `␍` prettier/prettier Vue 可悬浮按钮

    Delete `␍` prettier/prettier 代码格式化不一致,换行符冲突.UNIX/Linux 使用的是 0x0A(LF), DOS/Windows 一直使用 0x0D0A(CRLF) ...

  2. 安装 deepin linux 系统、linux 使用记录

    安装 deepin 深度linux系统 官网:https://www.deepin.org/zh/ 包含了下载ios镜像和安装教程: 最新版本:https://www.deepin.org/zh/do ...

  3. huawei--配置链路聚合

    huawei--配置链路聚合 项目要求: LSW1和LSW2之间配置链路聚合,链路聚合分为手工和lacp两种模式.配置完后查看链路聚合状态. 项目实施: (vlan10 20 30的创建命令vlan ...

  4. pyqt5离线安装教程

    目前总结的安装pyqt5,需要的离线安装包,除了每一个包要跟系统版本适配之外,还要考虑包跟包之间的适配.pyqt5跟它开头的一些包要保持是同一个版本,至少有2个小数点的位数是一样的才行,qt5跟它开头 ...

  5. vue3使用echarts插件并实现点击下载图表功能

    接到一个新的需求,就是用vue3制作一幅世界地图,并实现点击下载按钮将图表转变为图片下载到本地. 使用插件: html2canvasnpm安装: npm install html2canvas组件引入 ...

  6. [Err] [Dtf] 1044 - Access denied for user 'root'@'localhost' to database 'information_schema'

    在从Oracle向mysql数据库传输数据时,报出来这个错误,原因是因为没有打开mysql数据库,在navicat里打开mysql,并选中要传输的数据库 再重复传输一下即可

  7. “初始化 Java 工具”期间发生了内部错误, java.lang.NullPointerException

    今天刚打开eclipse就报了这个错误,我怀疑是昨晚想关电脑的时候,关闭eclipse太快,没有等待工作空间保存就关了电脑的缘故 错误如图: (图片来自下方链接博客,因为忘记截图了) 我百度后按照提示 ...

  8. 在Excel中创建随机数据集

    1.随机小数0-1之间 =RAND() 2.随机整数1-100之间 =RANDBETWEEN(1,100) 3.生成一定比例的随机数0或1 =IF(RAND()>=0.8,1,0) 4.生成一定 ...

  9. 借助mapshaper的简化来修复geojson的拓扑错误

    在使用turf.union方法合并面的时候,报错了.无法全部合并完成. 按照提示说是出现线的拓扑错误.至于哪里错误也看不出来. turf不提供拓扑修正功能的js包 难道有转到arcgis中去修复?好搓 ...

  10. 【DM论文阅读杂记】复杂社区网络

    Paper Title Community Structure in Time-Dependent, Multiscale, and Multiplex Networks Basic algorith ...