drf知识--02

APIView执行流程分析

源码分析:
# 1 在路由中:path('books/', views.BookView.as_view()),请求来了
# 2 先看 as_view()---->APIView的 as_view---》as_view执行结果跟之前一样,去除了csrf认证@classmethoddef as_view(cls, **initkwargs):view = super().as_view(**initkwargs) # 调用父类的 as_view,view还是View的as_view# 以后所有请求,都不会做csrf认证了return csrf_exempt(view)# 3 请求来了执行 views.BookView.as_view()(request)--->view(request)--->csrf_exempt(view)(request)--->内部核心---》return self.dispatch(request)
# 4 self 是 APIView类的对象---》APIView没有dispatch---》APIView的dispatch,核心代码如下def dispatch(self, request, *args, **kwargs):# 后续的request都是 initialize_request 返回结果--》新的request--》drf的Requet类的对象request = self.initialize_request(request, *args, **kwargs)# 新的request放到了 self.request中---》self是BookView类的对象# 后续视图类的方法中 可以直接 self.request取出 当次请求的request对象self.request = requesttry:# 执行了三大认证:'''self.perform_authentication(request)self.check_permissions(request)self.check_throttles(request)'''self.initial(request, *args, **kwargs)###### 通过反射,去视图类中:BookView中执行跟请求方式同名的方法if request.method.lower() in self.http_method_names:handler = getattr(self, request.method.lower(),self.http_method_not_allowed)else:handler = self.http_method_not_allowed# request是新的Request类的对象了  get方法的第一个参数request也是新的response = handler(request, *args, **kwargs)########################执行视图类的方法结束######except Exception as exc:# 如果在执行三大认证或视图类方法中,出了错,都会被异常捕获,统一处理response = self.handle_exception(exc)self.response = self.finalize_response(request, response, *args, **kwargs)return self.response# 5 看self.initialize_request 是APIView的def initialize_request(self, request, *args, **kwargs):# 类实例化得到对象,传入一些参数# Request类--》drf提供的类from rest_framework.request import Requestreturn Request(request,parsers=self.get_parsers(),authenticators=self.get_authenticators(),negotiator=self.get_content_negotiator(),parser_context=parser_context)

# 总结:
    1 以后视图类方法中得request对象,变成了新的request,它是rest_framework.request.Request 的对象了,但是用起来跟之前一样
    2 把新的request对象,同时放到了 视图类的对象中  self.request = request  后续从视图类中可以直接通过 self.request取出来
    3 在执行视图类的方法之前,执行了三大认证
    4 如果三大认证或视图类的方法执行出错,会有全局异常处理
    5 以后所有的接口都去除了csrf认证

Request对象分析(难--记总结)

# 分析APIVIew时,分析出,以后request都是新的request

        是drf提供的Request的对象   from rest_framework.request import Request

# 源码解析之 __init__--->老的request在新的内部---》request._request:
# 先看 __init__--->类实例化得到对象时,对对象进行初始化,往对象中放数据def __init__(self, request, parsers=None, authenticators=None,negotiator=None, parser_context=None):# 传入的request是老的,django原生的request# 放到了self._request,self 是新的request类的对象self._request = requestself._data = Emptyself._files = Empty                                        request = self.initialize_request(request, *args, **kwargs)  # 前面是新的,后面是老的return Request(request)    # 老的

# 以后用新的跟用老的一样, 是因为新的request包含了老的,并且还有自己的新功能
# 魔法方法:在类内部,以 __开头  __结尾的方法, 在某种情况下会自动调用,他们称之为魔法方法
            __init__:  在调用类名()会自动触发
            __str__:   print对象时自动触发  
      还有很多,所有类都继承object类,它都在object类中


  #  __getattr__ :通过对象.属性 ,属性不存在时会触发

def __getattr__(self, attr):try:# 通过反射,去老的中取,能取到就返回,取不到,执行except代码,再取不到就报错return getattr(self._request, attr)except AttributeError:return self.__getattribute__(attr)

# APIView中的request :
    1 新的request中有老的requet, 在request._request
    2 新的request 多了data属性,客户端提交的请求体中得数据

                无论以那种方式编码,都在request.data中
    3 其他的使用,跟之前老request一模一样

request.method
request.path
request.POST
request.GET
request.FILES
。。。

# 总结:
1 原生django的post方法处理提交数据,只能处理urlencoded和form-data编码

                从request.POST中取
2 原生djagno的put处理不了提交的数据,需要我们自己从body中取出来处理
        -分不同编码格式:
            urlencoded:name=lqz&age=19     # 用字符串切割
            json:{"xxz":"xx","yyz":"yyy"}           # 要用json.loads  进行反序列化          
3 原生django不能处理json提交的数据,需要自己做(put,post)
4 新的request解决了所有问题     # request.data   

序列化类介绍

# 序列化类可以干的事:
            序列化qs对象,单个对象,做序列化给前端
            前端传入数据,校验数据是否合法
           反序列化,前端传入数据,存到数据库中

# 继承APIView+Response实现 Publish的5个接口

class PublishView(APIView):def get(self, request):publish_list = Publish.objects.all()l = []for publish in publish_list:l.append({'name': publish.name, 'addr': publish.addr})return Response({'code': 100, 'msg': '查询所有成功', 'results': l})def post(self, request):# 如果是urlencoded编码,这种方式不行 publish = Publish.objects.create(**request.data)publish = Publish.objects.create(name=request.data.get('name'), addr=request.data.get('addr'))return Response({'code': 100, 'msg': '新增成功', 'results': {'name': publish.name, 'addr': publish.addr}})
class PublishDetailView(APIView):def get(self, request, pk):publish = Publish.objects.filter(pk=pk).first()return Response({'code': 100, 'msg': '查询单条成功', 'results': {'name': publish.name, 'addr': publish.addr}})def put(self, request, pk):publish = Publish.objects.filter(pk=pk).first()publish.name = request.data.get('name')publish.addr = request.data.get('addr')publish.save()return Response({'code': 100, 'msg': '修改成功', 'result': {'name': publish.name, 'addr': publish.addr}})def delete(self, request, pk):Publish.objects.filter(pk=pk).delete()return Response({'code': 100, 'msg': '删除成功'})

序列化类的使用

#  drf 提供的序列化器,实现序列化,反序列化和数据校验 

# 使用步骤:
1、写个py文件,叫serializer.py
 2、写个类,继承serializers.Serializer
3、在类中写要序列化的字段:

class PublishSerializer(serializers.Serializer):name = serializers.CharField()     # 写字段,要序列化的字段addr = serializers.CharField()id = serializers.IntegerField()

4、在视图类中使用,完成  序列化:

多条:
ser = PublishSerializer(instance=publish_list, many=True)      
ser.data  序列化后的数据
单条:
ser = PublishSerializer(instance=publish)      
ser.data  序列化后的数据

序列化类快速使用

# 视图类:
from .serializer import PublishSerializer
class PublishView(APIView):def get(self, request):publish_list = Publish.objects.all()ser = PublishSerializer(instance=publish_list, many=True)  # 如果序列化多条,要many=Truereturn Response({'code': 100, 'msg': '查询所有成功', 'results': ser.data})class PublishDetailView(APIView):def get(self, request, pk):publish = Publish.objects.filter(pk=pk).first()ser = PublishSerializer(instance=publish)  # 单个不写many=Truereturn Response({'code': 100, 'msg': '查询单条成功', 'results': ser.data})
# 序列化类:
from rest_framework import serializers
class PublishSerializer(serializers.Serializer):# 写字段,要序列化的字段name = serializers.CharField()# addr = serializers.CharField()id = serializers.IntegerField()
# 路由
urlpatterns = [path('publish/', views.PublishView.as_view()),path('publish/<int:pk>', views.PublishDetailView.as_view()),
]

序列化类反序列化校验

# 序列化类中可以做字段校验, 三层
 第一层:字段自己的serializers.CharField(max_length=12,min_length=3)
 第二层:局部钩子

def validate_name(self, name):if name.startswith("sb"):# 抛异常raise ValidationError('不能以sb开头')return namedef validate_addr(self, addr):if 'sb' in addr:# 抛异常raise ValidationError('地址中不能有sb')return addr

第三层:全局钩子(注意:前端多传的,这里不会有) 

def validate(self, attrs):print(attrs)# 多个字段同时校验# 出版社名和地址不能一样---》出版社前3个字不能和地址前3个字一样if attrs.get('name')[:3] == attrs.get('addr')[:3]:raise ValidationError('出版社名和地址不能一样')return attrs

# 视图类中:

from .serializer import PublishSerializerClass PublishView(APIView):def get(self,request):publish_list = Publish.objects.all()ser = PublishSerializer(instance=publish_list, many=True)  # 如果序列化多条,要many=Truereturn Response({'code': 100, 'msg': '查询所有成功', 'results': ser.data})def post(self,request):ser = PublishSerializer(data=request.data)  # 把待校验数据传入if ser.is_valid():     # 做数据校验---》三层print(ser.data)else:print(ser.errors)  # 没有校验通过,打印错误信息

序列化类保存

# 保存

1、在序列化类中,保存必须重写 create,完成真正的保存

def create(self, validated_data):# validated_data 校验过后的数据---》多传的数据,在这没有publish = Publish.objects.create(**validated_data)return publish  # 不要忘了返回新增的对象---》后续会拿着这个对象做序列化  ser.data--->根据它做序列化的

2、在视图类中,数据校验通过后,调用ser.save()
       
# 修改功能,也要校验和保存

1 在序列化类中,必须重写 update,完成真正的修改
def update(self, instance, validated_data):  # {name:上海出版社,add:上海地址}# instance.name=validated_data.get('name')# instance.addr=validated_data.get('addr')# instance.save() # publish 对象的save---》保存到数据中for keyy in validated_data:setattr(instance,key,validated_data[kkey])instance.save()return instance2 视图类中
ser = PublishSerializer(instance=publish, data=request.data)
ser.save() # 虽然新增或修改都是调用save,但是内部做了判断

今日思维导图:

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

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

相关文章

C# WPF上位机开发(文件对话框和目录对话框)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 一个上位机软件在处理数据的时候&#xff0c;除了配置文件、数据文件之外&#xff0c;一般还需要使用选择对话框进行文件和目录的选取。如果不这样…

20231222给NanoPC-T4(RK3399)开发板的适配原厂Android10的挖掘机方案并跑通AP6398SV

20231222给NanoPC-T4(RK3399)开发板的适配原厂Android10的挖掘机方案并跑通AP6398SV 1、简略步骤&#xff1a;rootrootrootroot-X99-Turbo:~/3TB/3399-android10$ cat Rockchip_Android10.0_SDK_Release.tar.gz0* > Rockchip_Android10.0_SDK_Release.tar.gz rootrootrootro…

C++进阶-继承

继承 一、继承的概念及定义1.1 继承的概念1.2 继承的定义1.2.1 定义格式1.2.2 继承关系和访问限定符1.2.3 继承基类成员访问方式的变化 二、基类和派生类对象赋值转换三、继承中的作用域3.1 同名成员变量3.2 同名成员函数 四、派生类的默认成员函数五、继承与友元六、继承与静态…

Leetcode—43.字符串相乘【中等】

2023每日刷题&#xff08;六十八&#xff09; Leetcode—43.字符串相乘 算法思想 实现代码 class Solution { public:string multiply(string num1, string num2) {int len1 num1.size(), len2 num2.size();string ans;int end1 len1 - 1, end2 len2 - 1;int arr[len1 l…

、写入Shellcode到注册表上线

其实本质就是将shellcode写入到注册表中&#xff0c;然后读取注册表中的shellcode&#xff0c;然后创建线程去执行shellcode。 如下图: 写入注册表shellcode 这里将shellcode写入到注册表中&#xff0c;在我们需要的时候再去读取然后执行。 这里用到如下两个Windows API函…

福FLUKE禄克8808A数字多用表

福禄克8808A&#xff0c;用于制造、研发、维修等应用的多功能数字表&#xff0c;FLUKE 8808A 5.5位数字多用表可以完成当今众多常用的测量工作。无论是功能测 展开 福禄克8808A&#xff0c;用于制造、研发、维修等应用的多功能数字表&#xff0c;FLUKE 8808A 5.5位数字多用表可…

【音视频】remb twcc原理

目录 twcc简介 WebRTC REMB 参考文档 twcc简介 TWCC全称是Transport wide Congestion Control&#xff0c;是webrtc的最新的拥塞控制算法。其原理是在接收端保存数据包状态&#xff0c;然后构造RTCP包反馈给发送端&#xff0c;反馈信息包括包到达时间、丢包状态等&#xff…

室内导航技术在智慧医疗的革新应用

随着科技的飞速发展&#xff0c;智慧医疗已经成为现代医疗服务的重要组成部分。在这个背景下&#xff0c;室内导航技术逐渐崭露头角&#xff0c;为智慧医疗建设带来了革命性的改变。本文将深入探讨室内导航技术在智慧医疗中的应用&#xff0c;并分析其为医疗服务带来的诸多便利…

vue:ref的作用和实例

定义&#xff1a;用来获取元素或子组件注册或者引用信息&#xff0c;父组件通过$ref获取到相应的DOM对象和子组件 1、vue中ref的作用 获取页面的DOM元素获取子组件的对象&#xff08;也是一种通信方式&#xff09; 2、实例 1、获取DOM&#xff0c;首先创建一个父页面index然…

如何自定义右键弹框并实现位置自适应?

一、问题 右键显示弹框&#xff0c;但是靠近浏览器边缘的部分会被隐藏&#xff0c;需要实现弹框位置自适应 二、 问题分析 如果想要最终弹框的宽高不超过屏幕视口&#xff0c;就等于屏幕视口的总宽/高减去弹框打开时的起点坐标&#xff0c;剩下的部分大于等于弹框的宽/高&…

商家如何进行商业模式开发,助力产品更好的销售模式?

商家如何进行商业模式开发&#xff0c;助力产品更好的销售模式&#xff1f; 随着各类电商平台的疯狂崛起&#xff0c;越来越多的商家对其中带来的高额回报率产生心动&#xff0c;毕竟对于线上的场景来说&#xff0c;即省去了房租、水电、仓储以及其他各种费用&#xff0c;用电商…

vue3 + TypeScript使用国际化

vue3 TypeScript使用国际化 本文使用了 Vite 构建工具创建的vue3项目Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块Vite 官方中文文档当然如果你的vue3项目未使用vite,你也可以为你的旧项目提提速&#xff0c;安装vite &#xff0c;安装方法在上一个博客…

【华为数据之道学习笔记】6-5数据地图的核心价值

数据供应者与消费者之间往往存在一种矛盾&#xff1a;供应者做了大量的数据治理工作、提供了大量的数据&#xff0c;但数据消费者却仍然不满意&#xff0c;他们始终认为在使用数据之前存在两个重大困难。 1&#xff09;找数难 企业的数据分散存储在上千个数据库、上百万张物理表…

汽车行业一些知识

一、汽车术语集合 1、 轴距(mm)&#xff1a;汽车前轴中心至后轴中心的距离。 2、转弯半径(mm)&#xff1a;汽车转向时&#xff0c;汽车外侧转向轮的中心平面在车辆支撑平面上的轨迹圆半径。转向盘转到极限位置时的转弯半径为最小转弯半径。 3、最大总质量(kg)&#xff1a;汽…

动态数组的实现

定义 1. 在计算机科学中&#xff0c;数组是由一组元素&#xff08;值或变量&#xff09;组成的数据结构&#xff0c;每个元素有至少一个索引或键来标识。 2. 因为数组内的元素是连续存储的&#xff0c;所以数组中元素的地址&#xff0c;可以通过其索引计算出来。 3. 知道了数…

计算机网络-网络层

计算机网络-网络层 以下笔记整理为哔哩哔哩湖科大教书匠的《计算机网络微课堂》的教学视频。 链接&#xff1a;计算机网络微课堂 1. 网络层概述 1.1 网络层的主要任务是实现网络互联&#xff0c;进而实现数据包在各网络之间的传输。 1.2 要实现网络层任务&#xff0c;需要解决…

【飞凌 OK113i-C 全志T113-i开发板】一些有用的常用的命令测试

一些有用的常用的命令测试 一、系统信息查询 可以查询板子的内核信息、CPU处理器信息、环境变量等 二、CPU频率 从上面的系统信息查询到&#xff0c;这是一颗具有两个ARMv7结构A7内核的处理器&#xff0c;主频最高1.2GHz 可以通过命令查看当前支持的频率以及目前所使用主频 …

Spring IoCDI

文章目录 前言什么是Spring1. 什么是 IoC 容器1.1 什么是容器1.2 什么是 IoC 2. 什么是DI IoC & DI 的使用IoC详解Bean的存储Controller注解如何获取Bean1. 根据Bean的名称获取Bean2. 根据Bean类型获取Bean3. 根据Bean名和Bean类型获取Bean Service注解Repository注解Compo…

使用Docker一键部署Uptime Kuma,并将监控服务映射至公网访问

文章目录 **主要功能**一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用本教程安装。本教程使用Docker部署服务&#xff0c;如何安装Docker详见&#xff1a; 二、Docker部署Uptime Kuma三、实现公网查看网站监控四、使用固定公网地址访问…

go语言初体验1--使用go install

当安装后go语言后。 尝试编写go程序。 当使用 go install 命令&#xff0c;报错。 go: go install requires a version when current directory is not in a moduleTry go install jvmgo\ch01latest to install the latest version通过查找资料。 用命令&#xff1a; go env …