Django框架之drf:5、反序列化器校验部分源码分析、断言、drf之请求与响应、视图组件介绍及两个视图基类、代码部分实战
Django框架之drf
一、反序列化类校验部分源码解析
反序列化校验什么时候开始执行校验?
剖析流程一:在视图中使用反序列化器实例化的对象调用is_valid()的时候就会进行校验,通贩校验返回True,反之False
    class BookView(APIView):
		# 新增
		def post(self, request):
			ser_obj = BookSerializer(data=request.data)
          # 触发反序列化类校验
			if ser_obj.is_valid():
            ser_obj.save()
            return Response({'code': 100, 'msg': '新增图书成功', 'result': ser_obj.data})
          return Response({'code': 101, 'msg': ser_obj.errors})
解析流程二:入口:ser.is_valid() 是序列化类的对象,假设序列化类是BookSerializer---》is_valid---》找不到,在父类中找到BaseSerializer
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
二、断言
 用于判断一个表达式,在表达式的条件为False时会触发异常,反之正常往下执行代码,断言可以在条件不满足的时候主动抛出异常
关键词:assert
用法:
name = 'kangkang'
# 如果name不等于'kangkang',那么将会直接抛出异常代码
assert name== 'kangkang'
print('正确,正常执行')


三、drf之请求
1、Request能够解析的前端传入编码格式
drf为我们提供了三种编码格式分别是:
- 第一种:rest_framework.parsers.JSONParser - 对应前端的:json格式数据
 
- 第二种:rest_framework.parsers.FormParser - 对应前端的:form-data格式数据
 
- 第三种:rest_framework.parsers.MultiPartParser - 对应前端的:urlencode
 


配置请求编码的方法:
 这三种编码在默认都是开启的,配置的方法有两种:
- 在视图类中配置(局部) 
- django的settings.py文件中配置(全局) 
导入模块:(三种请求模块)
    from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
# 方式一:在视图类中配置(只会影响该视图类下的方法)
    class BookView(APIView):
        parser_classes = ['JSONParser', 'FormParser', 'MultiPartParser']
# 方式二:django的settings.py中配置(影响全局)
	REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser',
    ],
    }
# 方式三:全局配了1个,某个视图类想要3个,怎么配?
    -只需要在视图类,配置3个即可
    -因为:先从视图类自身找,找不到,去项目的drf配置中找,再找不到,去drf默认的配置找
2、Request类中的属性和方法
# 该节在上述中已经讲过,此处只做总结
	继承APIView的视图类中的request是经过drf处理后的requset,该类不仅包含了django原生的request的所有方法,还新增了以下功能
    1、request.data  # (所有请求数据都可以在这里取出,升级版的request.body)
    2、__getattr__	# 该魔法方法是新的request中的方法,调用不存在的方法会回到老的requert中去找
    3、query_params  # 和老的request.get用法一致
四、drf之响应
1、Response能够响应的编码格式
 drf是django的一个app,所以需要在django的settings.py中进行配置,否则浏览器将无法正常访问
 drf的响应,使用浏览器和postman访问同一个接口,返回的格式是不一样的,如果是浏览器将会返回的格式好看一点,postman直接返回数据本身。响应的格式共有两种,配置方法类似于请求的配置方法
配置方法:
导入模块:(两种响应方式模块)
	from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
# 方式一:视图类中配置(局部配置,不会影响全局)
	class BookView(APIView):
    	renderer_classes=[JSONRenderer,]
# 方式二、django中配置项目文件(全局配置,局部配置的话优先采用局部)
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': [
            'rest_framework.renderers.JSONRenderer',
            'rest_framework.renderers.BrowsableAPIRenderer',
        ],
    }
# 方式三:使用顺序(一般就用内置的即可)
	优先使用视图类中的配置,其次使用项目配置文件中的配置,最后使用内置的
2、Response的源码属性或方法
Response源码分析
# 导入Response模块:
    from rest_framework.response import Response
# Response init可以传的参数
    def __init__(self,
             data=None,
             status=None,
             template_name=None,
             headers=None,
             exception=False,
             content_type=None)
# data:
	之前咱们写的ser.data,可以是字典或列表,字符串---》序列化后返回给前端---》前端在响应体中看到的就是这个 
# status:
	http响应的状态码,默认是200,可以通过导入模块进行修改
        -from rest_framework.status import HTTP_200_OK
        -Response('xxx',status=status.HTTP_200_OK)
# template_name:
	解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子,后期公司可以自己定制
# headers:
	响应头,http响应的响应头
   		原生django,响应头中添加数据
        obj = HttpResponse('dddd')
            obj['xxc'] = 'yyc'
 		         return obj
# content_type :
	响应编码格式,一般不动
五、视图组件介绍及两个视图基类
APIView是drf提供的视图类中最顶层的视图基类
1、APIView与View区别
- 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象
- 视图方法可以返回REST framework的Response对象
- 任何APIException异常都会被捕获到,并且处理成合适的响应信息
- 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制(执行三大认证)
2、视图基类
APIVIew
	-类属性:
    renderer_classes  # 响应格式
    parser_classes  # 能够解析的请求格式
    authentication_classes  #认证类
    throttle_classes  # 频率类
    permission_classes  # 权限类
六、基于APIView+ModelSerializer+Resposne写5个接口
1、视图类
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
from .models import Book
class BookView(APIView):
    # 查询多条
    def get(self, request):
        book_obj_all = Book.objects.all()
        serializer_obj = BookSerializer(instance=book_obj_all, many=True)
        return Response(serializer_obj.data)
    # 新增
    def post(self, request):
        res_obj = BookSerializer(data=request.data)
        res_obj.is_valid(raise_exception=True)
        res_obj.save()
        return Response({'cede': 100, 'msg': '新增成功', 'result': res_obj.data})
class BookDetailView(APIView):
    # 查询单条
    def get(self, request, *args, **kwargs):
        book_obj = Book.objects.filter(**kwargs).first()
        serializer_obj = BookSerializer(instance=book_obj)
        return Response(serializer_obj.data)
    # 修改
    def put(self, request, *args, **kwargs):
        target_book_obj = Book.objects.filter(**kwargs).first()
        serializer_obj = BookSerializer(instance=target_book_obj, data=request.data)
        serializer_obj.is_valid(raise_exception=True)
        serializer_obj.save()
        return Response({'code': 100, 'msg': '修改成功', 'result': serializer_obj.data})
    # 删除
    def delete(self, request, *args, **kwargs):
        Book.objects.filter(**kwargs).delete()
        return Response({'code': 100, 'msg': '删除成功'})
2、序列化类
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Book
# 序列化类
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        # 绑定的表
        model = Book
        # 序列化的字段
        fields = ['pk', 'name', 'price', 'authorList', 'publishDetail', 'author', 'publish']
        # 字段校验条件
        extra_kwargs = {
            'name': {'max_length': 32},
            'authorList': {'read_only': True},
            'publishDetail': {'read_only': True},
            'author': {'write_only': True},
            'publish': {'write_only': True}
        }
    # 全局钩子
    def validate(self, attrs):
        if int(attrs.get('price')) > 100:
            raise ValidationError('价格不能超过100元')
        return attrs
3、路由
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    # 查询多条、新增接口
    path('book/', views.BookView.as_view()),
    # 查询单条、修改、删除接口
    path('book/<int:pk>/', views.BookDetailView.as_view())
]
4、模型类
from django.db import models
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    author = models.ManyToManyField(to='Author')
    # 外键字段数据序列化功能函数
    def authorList(self):
        author_data_list = [{'name': author_obj.name,
                             'phone': author_obj.phone,
                             'age': author_obj.authorinfo.age,
                             'address': author_obj.authorinfo.gender
                             } for author_obj in self.author.all()]
        return author_data_list
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, null=True)
    # 外键字段数据序列化功能函数
    def publishDetail(self):
        return {'name': self.publish.name, 'address': self.publish.address}
class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=11)
    authorinfo = models.OneToOneField(to='AuthorInfo', on_delete=models.CASCADE, null=True)
class AuthorInfo(models.Model):
    age = models.CharField(max_length=8)
    gender = models.CharField(max_length=8)
class Publish(models.Model):
    name = models.CharField(max_length=32)
    address = models.CharField(max_length=32)
七、基于GenericAPIView+5个视图扩展类
1、视图类
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, \
    RetrieveModelMixin
from .serializer import BookSerializer
from .models import Book
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,
                     DestroyModelMixin,
                     UpdateModelMixin):
    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.delete(request, *args, **kwargs)
2、序列化类
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Book
# 序列化类
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        # 绑定的表
        model = Book
        # 序列化的字段
        fields = ['pk', 'name', 'price', 'authorList', 'publishDetail', 'author', 'publish']
        # 字段校验条件
        extra_kwargs = {
            'name': {'max_length': 32},
            'authorList': {'read_only': True},
            'publishDetail': {'read_only': True},
            'author': {'write_only': True},
            'publish': {'write_only': True}
        }
    # 全局钩子
    def validate(self, attrs):
        if int(attrs.get('price')) > 100:
            raise ValidationError('价格不能超过100元')
        return attrs
3、路由
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    # 查询多条、新增接口
    path('book/', views.BookView.as_view()),
    # 查询单条、修改、删除接口
    path('book/<int:pk>/', views.BookDetailView.as_view())
]
4、模型类
from django.db import models
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    author = models.ManyToManyField(to='Author')
    # 外键字段数据序列化功能函数
    def authorList(self):
        author_data_list = [{'name': author_obj.name,
                             'phone': author_obj.phone,
                             'age': author_obj.authorinfo.age,
                             'address': author_obj.authorinfo.gender
                             } for author_obj in self.author.all()]
        return author_data_list
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, null=True)
    # 外键字段数据序列化功能函数
    def publishDetail(self):
        return {'name': self.publish.name, 'address': self.publish.address}
class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=11)
    authorinfo = models.OneToOneField(to='AuthorInfo', on_delete=models.CASCADE, null=True)
class AuthorInfo(models.Model):
    age = models.CharField(max_length=8)
    gender = models.CharField(max_length=8)
class Publish(models.Model):
    name = models.CharField(max_length=32)
    address = models.CharField(max_length=32)
Django框架之drf:5、反序列化器校验部分源码分析、断言、drf之请求与响应、视图组件介绍及两个视图基类、代码部分实战的更多相关文章
- DRF框架(五)——context传参,二次封装Response类,两个视图基类(APIView/GenericAPIView),视图扩展类(mixins),子类视图(工具视图),视图集(viewsets),工具视图集
		复习 1.整体修改与局部修改 # 序列化get (给前端传递参数) #查询 ser_obj = ModelSerializer(model_obj) #只传递一个参数,默认是instance的参数,查 ... 
- DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render
		DRF框架 全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ... 
- drf 认证校验及源码分析
		认证校验 认证校验是十分重要的,如用户如果不登陆就不能访问某些接口. 再比如用户不登陆就不能够对一个接口做哪些操作. drf中认证的写法流程如下: 1.写一个类,继承BaseAuthenticatio ... 
- drf的基本使用、APIView源码分析和CBV源码拓展
		cbv源码拓展 扩展,如果我在Book视图类中重写dispatch方法 -可以实现,在get,post方法执行之前或者之后执行代码,完成类似装饰器的效果 def dispatch(self, requ ... 
- drf复习(一)--原生djangoCBV请求生命周期源码分析、drf自定义配置文件、drf请求生命周期dispatch源码分析
		admin后台注册model 一.原生djangoCBV请求生命周期源码分析 原生view的源码路径(django/views/generic/base.py) 1.从urls.py中as_view ... 
- okhttp框架源码分析从同步&异步请求使用开始
		对于okhttp在如今项目中的普及程度已经不言而喻啦,基本上如今网络请求都会基于它去进行封装,而非前几年用Android的网络框架HttpURLConnection和Apache HttpClient ... 
- sentinel流控规则校验之源码分析
		前言: 上节给大家把sentinel流控整个执行大致过了,但涉及到最核心的流控算法还没有讲,先提前说明一下 sentinel用的流控算法是令牌桶算法,参考了Guava的RateLimiter,有读过R ... 
- *CI框架装载器Loader.php源码分析
		http://www.bitscn.com/pdb/php/201411/404680.html 顾名思义,装载器就是加载元素的,使用CI时,经常加载的有: $this->load->li ... 
- DRF中两大视图基类APIView/GenericAPIView的介绍
		(1)APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父类. APIView与V ... 
- IK分词器原理与源码分析
		原文:http://3dobe.com/archives/44/ 引言 做搜索技术的不可能不接触分词器.个人认为为什么搜索引擎无法被数据库所替代的原因主要有两点,一个是在数据量比较大的时候,搜索引擎的 ... 
随机推荐
- MyBatis笔记03------XXXMapper.xml文件解析
			SQL映射文件的配置解析 当我们写好mapper(dao)层接口时,然后在对应的XXXMapper.xml文件中写业务逻辑对应的SQL映射语句,通过这个文件中可以实现CRU操作,那么下面说明如何编写这 ... 
- vue3中的defineProps,watch,computed
			在vue3的setup语法糖中,defineProps不需要引入了 <script setup> import { computed } from '@vue/reactivity'; i ... 
- jupyter notebook使用相对路径的方法
			在当前文件夹路径下开启jupyter notebook 这样就可以直接使用相对路径了,而不用管绝对路径这一令人心烦的问题 首先需要重新安装PowerShell 下载链接:https://cloud.1 ... 
- 如何在 .NET MAUI 中加载 json 文件?
			引言: 按core传统方式添加 AddJsonFile("appsettings.json") 在windows平台和ssr工作正常,但是在 ios 和 android 无法用这种 ... 
- Day11.2:标签的使用
			标签的使用 当我们在嵌套语句中,例如当我们在for的嵌套循环语句中,想要终止或重新开始当前循环以外的循环的时候,单独仅靠break和continue和还不够,需要在我们想要作用的循环语句处加上一个标签 ... 
- Web安全Day1 - SQL注入、漏洞类型
			Web安全Day1 - SQL注入.漏洞类型 1. SQL注入 1.1 漏洞简介 1.2 漏洞原理 1.3 漏洞危害 2. SQL漏洞类型 2.1 区分数字和字符串 2.2 内联SQL注入 2.3 报 ... 
- i春秋exec
			打开是一个gif,提示文字未登录 话不多说,查看源码 发现vim字样,可能是文件泄露 直接在url后加/.index.php.swp来下载泄露文件 下载好了之后放vm上使用vim -r .index ... 
- 简单的sql注入2
			尝试 1 1' 1" 发现1'还是会报错,所以注入口还是1' 再试试1' and '1'='1发现报出SQLi detected! 取消空格试试1'and'1'='1 似乎可以进入,应该就是 ... 
- 重学c#系列——订阅发布与事件[二十六]
			前言 简单介绍一下订阅发布与事件. 正文 先来看一下委托的订阅与发布. public delegate void TestDelegate(); public class Cat { public T ... 
- apktool回编译报错
			报错 error: No resource identifier found for attribute 'XXX' in package 'XXX' 解决 将xml文件中 "http:// ... 
