drf : APIView执行流程和新的Request源码。APIView和Request对象分析
DRF基本使用及执行流程分析
1. 继承APIView使用
2. APIView的执行流程
路由: path('Book1',view.Book.as_view()) --> 第二个参数是函数的内存地址 --> APIView的as_view的执行结果 --> 本质还是用了View类的as_viewn内的viewc包函数,去掉了csrf的认证。--> 当请求来了-->触发view的闭包函数执行,并且传入request --> 调用了self.dispatch --> self是视图类的对象,从Book1中的找dispatch,但是找不到 --> 父类APIView中有 --> 本质执行dispatch是APIView类中的
"""APIView的as_view方法只是多了一个去掉csrf功能"""
APIView继承了Django的view
客户端发送请求,假设为get请求,先去类本身找as_view()方法,此时视图类BookAPIView中没有as_view()方法就去继承的APIView类中寻找,APIView中有as_view方法,执行,重写了as_view。
此时中间件无论是否注释,都不会执行。
# csrf的局部禁用-->在视图函数上加装饰器-->csrf_exempt装饰器-->装饰器本质就是一函数
# 装饰器的@ 是一个 语法糖(特殊语法) --> 把紧贴着的函数名当做参数传入装饰器中并且将返回结果赋值给函数名:index=csrf_exempt(index)
@csrf_exempt
def index(request):
pass
等同于
csrf_exempt(index)
此时要视图类继承APIView类,csrf中间件直接无效。
在执行self.dispatch() ---> APIView的dispatch
在视图类中使用的request对象是新的request对象,老的是request._request,新的request.GET拿到的还是老的GET,原理如下(Request类重写了双下getattr)
可以得出:
request._request.GET -最初始的request。
request._request -新request
那么为什么新的request可以与老request执行结果相同。
因为触发了__getattr__魔法方法,何为魔法方法?不需要主动调用,某种状态下会触发。
__getattr__ 对象.属性 会触发并执行
def __getattr__(self, attr):
"""
If an attribute does not exist on this instance, then we also attempt
to proxy it to the underlying HttpRequest object.
"""
try:
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
结论: 以后继承了APIView后,request对象成了新的,但是跟原来一样用。
新的request对象中有一个属性 data
data是post请求携带的数据 --- 字典
无论是什么编码格式,只要是post提交的数据,都在request.data中。
代码验证:
没有携带任何数据
新增unlencoded数据,request.POST与request.data都能接收
新增JSON格式数据,request.data
从body中取出,loads反序列化之后,转到request.data中
APIView和Request对象分析
以后如果使用drf,继承APIView(drf提供了很多view,他们都是继承自APIView),执行流程如下
-包装出一个新的request,在视图函数中使用时,跟原来没有区别。
-注意:取post提交的数据,不要从request.POST中取,从request.data中取
-注意:取get提交的数据,不要从request.GET中取,从request.query_params中取
# 将方法包装成数据属性
@property
def query_params(self):
"""
More semantically correct name for request.GET.
"""
return self._request.GET
Request类(drf) 中需要掌握的
- request.data
- request.query_params
- request.FIELS
APIView类
- 包装新的request
- 执行了认证,权限,频率
- 处理了全局异常
- 包装了request对象