# 课程链接
4天搞定django rest framework源码和实战_哔哩哔哩_bilibili
# 课程内容
(1)内容概要_略
(2)内容回顾_略
(3)django 视图之 CBV 基本使用
(4)django 视图之 CBV 源码流程
(5)django 视图之面试题和 csrf 补充
(6)django 视图之 CBV 和解决 csrf 认证
(7)以上内容梳理_略
【知识点补充---自己加的】
# 岂曰无衣,与子同袍
# (1)直接上图
# (2)Django 的 FBV 和 CBV
1)FBV 就是基于函数的视图, 就跟我们平时使用的一样。
2)CBV 是基于类的视图。就是要继承 django.views 中的 View 。见下图所示的代码。当执行了这一个类的时候,前端传来是什么请求,类就会自动执行相应的方法。比如 post 请求,那么类就会执行 post 的方法。
此时路由函数要这么写,就是要加 .as_view() 来作为路由函数,这里是固定的要求,不为什么。
那么上面就是一个 CBV 的模式。
# (3)postman 伪造请求
1)我们不可能为每一种请求再去设计相应的表单提交什么的,这没意义。我们可以使用 postman 这种工具来伪造各种请求,来查看后端返回的数据。
2)postman 的下载安装。下载链接:Download Postman | Get Started for Free
// 下载完成后,我们直接打开后就会自动安装了,并且在桌面生成快捷方式。这个时候打开该快捷方式,即如下图所示。其实 postman 有网页端,但是需要桌面代理才能测试本地的 url 。
3)postman 简单使用。如下图所示,我们点了加号之后的页面,然后我们也具体的使用了下,测试了 post 请求。这里的报错是因为我们没有关闭 django 中的 csrf 认证。这里可以直接去 settings.py 文件中的中间件处注释掉该认证即可。
# (4)列表生成式,直接给我写的代码和注释吧
# (5)面向对象
1)封装。体现在两个方面,一个方面是对同一类方法封装到类中。如下图所示,就是将各自类的对应自己方法,然后进行封装。
另外一个是将数据封装到对象中,就是我们将数据传入到类里面,然后里面的 self.a1 = 传参 a1,大致就是这个意思,供类的调用,也就是我们实例化这个类后,我们不仅能使用类的方法,还有里面的数据。
2)简单聊聊装饰器 @property,这个装饰器的作用会在别的数据分析的课里面细讲,我们只需要知道,在定义函数的前面引用。之后我们在调用该函数的时候,就可以不加括号了,就跟调用属性一样。见下面的代码块,算是一种入门级别的理解吧。
# -*- coding=utf-8 -*- # github: night_walkiner # csdn: 潘迪仔 class Foo: def __init__(self): self.price = 100 # (1) 装饰器,这里必须写在最前面,函数名就是后续调用时候用的, # 而且 @property 装饰后的函数,必须是返回某个值,然后调用是属性调用,就是对方法不用加括号 # 这里必须提一句,如果我们之后要赋值,比如下面的代码: """ 类 Foo 下的 @property def price(self,value): pass 之后调用的时候,如果我们 Foo.price 会提示少一个参数, 而如果我们这样 Foo.price(100) ,依然会报错, 因此我们要使用装饰器要求的设置,即下面的方式来设置数值什么的 """ @property def price(self): return print("装饰器") # 如果今后我们要对 price 进行赋值的话,必须装饰 price.setter , # 注意观察啊!!! @price.setter def price(self, value): self.price = value # 这个是一样的,也是要用(1) 中定义的 price 来 .deleter 作为装饰器 @price.deleter def price(self): del self.price
那么来上一个实例看看,就是武 sir 写的代码,我就不复现了。这里是也是封装实例的扩展,很简单。如果遇到问题去复现一下,或者研读下吧,不赘述了。
# (1)内容详细
1)关于 CBV 开发的结构。事实上 HTTP 请求本质上是发了一堆字符串,通过 /r 进行分隔的。但是我们是怎么处理请求的呢? Django 源码中是使用反射来做的,也就是 getattr() 方法来做。如果不使用反射方法,我们就要使用 request.method 去一个个做判断执行。(基本所有支持 CBV 结构的框架都是使用反射去实现的)
2)对于 CBV 而言,我们使用了这种模式的时候,实际上就是在路由地址,执行了 as_view() 的方法,然后我们可以看 as_view() 的源码,可以看到不论是执行什么请求,都要执行 self.dispatch()
3)self.dispatch 的源码如下,首先将获取的 request.method 的请求变小写,比如原来的是 GET 变成 get,然后判断这个请求是不是在 self.http_method_names 里面,这个self.http_method_names 里面存着的是各自请求类型,如 post,put 等等。 getattr(x, "y") 相当于 x.y 的意思,类似属性调用。
4)CBV 的具体流程
5)父类和子类的方法的执行顺序。见下图所示的代码:
如下图所示,比如当前是 post 请求,然后我们执行了 dispatch 方法。
第一: 那么系统就会从子类中找到 dispatch ,子类又会去父类里面找父类的 dispatch,但是 self 是代指子类,经过反射后找到的是 post 请求,
第二: 然后再从子类中调用 post 方法,将结果再返回给父类的 dispatch, 父类的 dispatch 再传回给子类的 dispatch ,然后再返回给用户。
# (1)CBV 源码流程的补充。相信这一块会随着深入学习而更扎实,且有更好的理解。
# (2) 继承
# (1)Django 中间件
1)Django 中间件最多只能写 5 个方法,就是下图列举的。以前说的 process_request() 和 process_response() 两种方法是最常用的而已。
其中 process_exception() 方法是只有异常的时候才会执行,没有异常就不会执行。对于 process_render_template() 方法,如果视图函数返回的是 render() 就会执行这个中间件,否则执行 HttpResponse() 的话是永远不会执行。
2)中间件的执行流程 _(Django 1.10 以上的版本),见下图所示,我们简述一下中间件的执行流程,当请求进来的时候:
第一:首先是按序执行所有中间件的 process_request() 方法,然后进行路由匹配,但是不执行视图函数;
第二:执行完路由匹配后,再返回第一层中间件,继续按序执行他们的 process_view() 方法,执行完后才开始执行视图函数;
第三:视图函数正确执行和返回(HttpResponse)的时候,就开始执行 process_response() 方法返回给浏览器。
第四:如果说,在执行路由函数时候发生错误,那么就会执行 process_exception() 方法返回异常;
第五:如果说,视图函数正确执行了,但是返回的是 render() 那么就执行中间件的process_render_template() 方法,然后返回给浏览器。
【第四、第五就是下图见注释的部分。】
3)使用中间件能做什么?比较常用的就是权限认证和用户登录认证。
# (2)csrf 认证的面试题
1)Django 中的中间件 csrf_token 的实现。csrf 的中间件是写在了 process_view() 方法里面的。【见后面的(3)的 3)的讲解】
# (3)免除 csrf 认证装饰器和单独 csrf 认证的装饰器
1)假设我们将全局的视图函数都添加了 csrf 认证,也就是在中间件的地方给 csrf 打开认证了,那么我们如果想免除某个视图函数的 csrf 认证就可以使用免除认证的装饰器了。那么导入的模块语句为:from django.views.decorators.csrf import csrf_exempt
如下图所示,那么我们在视图函数 users 前引用了 @csrf_exempt 就是免除该函数的 csrf 认证了。
2)场景二,如果我们注释了全局的 csrf 认证,又想对某几个特定的视图函数加上 csrf 认证,那么就可以使用单独的 csrf 装饰器了。导入模块的语句为:from django.views.decorators.csrf import csrf_protect 。使用方法是和免除的装饰器一样的。如下图所示。
3)有了上面的基础,我们就知道为什么 csrf 的认证需要写在 process_view() 中了,这是因为在执行认证的时候,需要检索这个视图函数是否免除了认证(或者带有认证),这里面是需要逻辑判断的。而如果写在 process_request() 方法中,请求过程并没有路由匹配的信息,csrf 都没找到视图函数,还谈什么检查视图函数是否带有相应的装饰器!紧接着,如果需要 csrf 认证,那么再去检查是否符合 csrf_token 的规则
# (1)CBV 怎么自定义 csrf 认证(自定义就是免除或是单独设置认证)
1)前面我们讲的都是基于 FBV 的来讲解 csrf 装饰器的用法的。那么对于 CBV 要自定义 csrf 认证的话,就不是简单的在类中的函数上加装饰器了。【csrf 装饰器就是 csrf_exempt 或者 csrf_protect】
2)解决方法就是使用 from django.utils.decorators import method_decorator 中的 method_decorator 装饰器,这可以对 CBV 结构设置自定义 csrf 装饰器用的。比如第一种方法就是如下的方法,@method_decorator(csrf_exempt) 那么就是免除这个视图类的 csrf 认证(对于单独设置也是一样的)。其实就是 @method_decorator(csrf 装饰器),只要是按照如下的格式就行。
class StudentsView(View): # 自定义认证---方法一, 就是放在 dispatch 方法前面。 # 这是官方规定的,没有为什么。 @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): print("before") # super() 不是简单的继承当前类的父类,而是执行整个继承关系 # 也就是说,找方法的时候,先在自己里面找,找不到采取父类找, # 如果父类再找不到,就去第二继承类去找 ret = super(StudentsView, self).dispatch(request, *args, **kwargs) # print(ret) print("after") return ret def get(self, request, *args, **kwargs): print("get") return HttpResponse("GET") # @method_decorator(csrf_exempt) 如果是加在这里是没用的!!! #(也就是对单独方法是无效的) # 因为官方规定了,就是要放在 dispatch 方法上面,而且 dispatch 还得放在最前面。 def post(self, request, *args, **kwargs): return HttpResponse("POST") def put(self, request, *args, **kwargs): return HttpResponse("PUT") def delete(self, request, *args, **kwargs): return HttpResponse("DELETE")
3)也可以是下面的方法,就是放在视图类的最上面,但是编写的时候就是@method_decorator(csrf 装饰器,name="dispatch")。具体见下面代码的注释。
from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt, csrf_protect # 自定义认证---方法二, name里面其实就是方法名。简单说就是找到这个类方法,然后加上这个装饰器 @method_decorator(csrf_exempt, name="dispatch") class StudentsView(View): def get(self, request, *args, **kwargs): print("get") return HttpResponse("GET") def post(self, request, *args, **kwargs): return HttpResponse("POST") def put(self, request, *args, **kwargs): return HttpResponse("PUT") def delete(self, request, *args, **kwargs): return HttpResponse("DELETE")
# 直接上图
# (1)getattr() 反射的使用。
还得提一点就是比如 getattr(obj, '_negotiator', None),就是返回 obj._negotiator,如果有的话。我们之前说了,如果没这个属性,反射就会报错,这个时候就可以用后面 None 了,意思是说,如果没有这个属性,系统也不报错,而是会返回一个 None。
# (2)类继承的优先级