CBV、APIView源码分析
一、CBV源码分析
1、功能需求
基于类的视图---> 使用类编写---> 在类中写跟请求方式(methon)同名的方法---> 路由配置 类名.as_view()
前端的请求过来,什么请求,就会执行跟请求方式同名的方法
2、执行流程
路由匹配成功---> 配置在路由上的第二个参:执行函数内存地址自动加(request)---> 执行view(request)---> 执行了self.dispatch --->BookView没有---> 找到了父类View---> dispatch--->
handler = getattr(self, 'get') 反射 ---> return handler(request, *args, **kwargs)
3、源码
# View.as_view的源码 @classonlymethod def as_view(cls, **initkwargs): # 闭包函数 def view(request, *args, **kwargs): self = cls(**initkwargs) # 类实例化得到对象:BookView的对象 # 调用对象的绑定方法 dispath---》去BookView中找dispatch--》找不到去父类---》View中的dispatch return self.dispatch(request, *args, **kwargs) # 对象的方法 return view # 执行:BookView.as_view()(request)---》本质是执行 View中as_view内部的view方法,传入了reuqest----》在执行View的dispatch方法,传入了request # 看 :View.dispatch---》源码 def dispatch(self, request, *args, **kwargs): if request.method.lower() in self.http_method_names: # 判断请求方式是否在那个固定的列表中[get, post...]---> # 反射:通过字符串 动态的 操作对象的属性或方法 # 假设是get请求---》去BookView中取出 get方法赋值给handler handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed # 执行handler加括号,传入了request # 本质是执行 get(request) return handler(request, *args, **kwargs)
二、APIView源码分析
1、
#1 使用drf,以后都写cbv---> 继承一个视图类---> 以后都继承drf提供 的APIView #2 APIView 继承了djagno的View #3 补充:这三个都是一个 from django.views import View from django.views.generic import View from django.views.generic.base import View # 4 继承APIView写cbv---> 执行起来跟之前效果一样---> 内部发生了非常大的变化 1 写视图类 from rest_framework.views import APIView class PublishView(APIView): def get(self, request): return JsonResponse({'code': 999}) 2 配置路由 path('publish/', PublishView.as_view()),
2、执行流程
路由匹配成功---》BookView.as_view()--->APIView的as_view配置在路由上的第二个参:执行函数内存地址(request)---》执行View的view(request)--》但是它去除了csrf认证---》dispatch---》APIView的dispatch---》 1 包装了新的request---》视图类的方法中的request是新的 2 执行三大认证 3 处理了全局异常
补充:
当流程来到View的view(request)时,这里是已去掉csrf验证的view,view闭包函数中会调用self.dispatch。这里的self是一个具体的对象,比如BookView。不能再直接点跳转,需要从根上BookView类开始找,---》APIview中找到
3、源码分析
# 比之前继承django的View多了如下 -0 去除了csrf认证 -1 包装了新的request -2 执行了认证,频率,权限 这三大认证 -3 全局异常处理:在视图类的方法中执行报错,会被异常捕获,做统一处理 # 执行流程分析 -请求来了---》执行PublishView.as_view()(request)--->PublishView类没有as_view---》找父类---》APIView的as_view -APIView的as_view---》本质在禁用csrf认证 @classmethod def as_view(cls, **initkwargs): # 调用父类的as_view得到返回值赋值给view---》django的View的as_view【看过】---》返回View的as_view的闭包函数 view view = super().as_view(**initkwargs) # 现在这个view就是原来看的View的as_view的view # 去除了csrf认证----》局部禁用csrf---》在视图函数上加 装饰器csrf_exempt # 加了装饰器的本质: 被装饰的函数=装饰器(被装饰的函数) return csrf_exempt(view) -PublishView.as_view()(request)--》执行了禁用掉csrf的View的as_view的view---》self.dispath--->APIView的dispath def dispatch(self, request, *args, **kwargs): # 1 包装了新的request对象 request = self.initialize_request(request, *args, **kwargs) # 把新的request,赋值给了 self.request # self 是 PublishView的对象 self.request = request try: # 2 执行了3大认证 self.initial(request, *args, **kwargs) ######开始### 跟之前View的dispath是一样的---》根据请求方式执行类中同名方法 ###执行视图类的方法 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 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 # 装饰器的本质 @auth # add=auth(add)-->以后调用add 实际上调用 auth(add)() def add(): pass add=auth(add) ### 包装新的request # 1 request.data:前端传入的数据(post,put,编码格式)--->写到在请求体中的数据,都用 # 2 老request中有 request.GET 新的使用request.query_params 充当 # 3 其他的所有属性方法,用起来跟之前一样 ### 三大认证 self.perform_authentication(request) self.check_permissions(request) self.check_throttles(request) ### 处理了全局异常,统一处理了
补充:
1 self.request = request 封装了新的request后赋值给调用对象的request。
在视图函数中打印: <rest_framework.request.Request: POST '/books/'>
2 三大认证
self.initial(request, *args, **kwargs)
self.perform_authentication(request) # 认证 self.check_permissions(request) # 权限 self.check_throttles(request) # 频率
4、 APIview总结:
视图类继承APIView视图类之后,多了
-0 去除了csrf认证
-1 新的request
-request.data
-request.query_params
-request.其他跟之前一样
-request._request 是老的
-2 三大认证
-3 全局异常