Django之DRF-APIView、View源码对比

前面的文章已经介绍过APIView与View的区别,或者说APIView比View更为强大的地方(文章链接:https://blog.****.net/weixin_47454485/article/details/107461486):

  • 1.传入到视图方法中的是Request对象,而不是Django的HttpRequest对象
  • 2.视图方法可以返回Response对象,自动处理(根据请求头的参数)为符合前端要求的格式
  • 3.任何APIException异常都会被捕获到,并且处理成合适的响应信息
  • 4.在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制

本文继续通过对比源码的方式来对以上4点进行分析

1.首先需要弄明白一个问题:
自定义一个视图类,继承View,又另外定义一个视图类,继承APIView,
问:这两个类的请求分别走的是哪个类的哪个函数,从as_view()和dispatch()来分析
答:继承View的自定义类请求走的View的dispatch()方法,继承APIView的自定义类请求走的APIView的dispatch()(可以参考前面的文章:https://blog.****.net/weixin_47454485/article/details/107505904)

2.明白了这个请求周期后可以发现,一个请求周期中最重要的函数就是dispatch(),进一步可以得出:APIView比View更为强高级之处就是APIView的dispatch()比View的dispatch()高级

3.对比源码
查看View的dispatch()方法,前面的文章已经讲过它的作用,这里不在描述
Django之DRF-APIView、View源码对比
查看APIView的dispatch()方法,
Django之DRF-APIView、View源码对比
可以看见APIView的dispatch()方法除了view的dispatch()的基本功能外,又增加一些代码,我们分区域来解析:
Django之DRF-APIView、View源码对比
大致是多了这四个模块,我们一个一个分析:

1.initialize_request

Django之DRF-APIView、View源码对比
可以看出,它是在实例化Request,返回一个request对象,这里不就是对应了文章开头的第一点
进去Request查看源码:
Django之DRF-APIView、View源码对比
实例化的参数有什么意义?它除了读配置,还是在读配置,然后完善成自己的request对象
Django之DRF-APIView、View源码对比
self._request = request,这行代码在干嘛呢,拷贝Django原生的request对象,换个名字_request,通俗来讲:我需要重写你,但是先保留你,如果用户要用原生的request,可以调_request,不影响使用
Django之DRF-APIView、View源码对比
这几行代码又在干嘛呢?还是读配置,有传就用,没有就配置空或者默认值
重点来了:
Django之DRF-APIView、View源码对比
这几行添加属性为什么是Empty、为什么是Empty、为什么是Empty,而不是None或者空串,进去Empty源码
Django之DRF-APIView、View源码对比
Empty是一个空类,类的操作性、变化性、扩展性更加强大,更加可以动态添加属性,所以说源码毕竟是源码,是真正的好代码

我们继续查看Request源码的query_params
Django之DRF-APIView、View源码对比
这个query_params不就是查询字符串参数!!说到底只是改了名字,换汤不换药,有可能是嫌弃原生的名字不好听

Request源码的data
Django之DRF-APIView、View源码对比
没有就加载,有就返回,继续进入_load_data_and_files()
Django之DRF-APIView、View源码对比
可以看见,把原生的POST和FILE

Request源码的__getattr__
Django之DRF-APIView、View源码对比
获取对象属性:先从Django原生的request对象中找,没有再往下调用不会报错的属性获取方法返回None

2.initial(request, *args, **kwargs)

Django之DRF-APIView、View源码对比
可以看出,它是在读配置,做认证、鉴权等,这里不就是对应了文章开头的第四点

3.try-except

捕获APIException异常,并且处理成合适的响应信息,这里不就是对应了文章开头的第三点

4.finalize_response(request, response, *args, **kwargs)

Django之DRF-APIView、View源码对比
可以看出,返回的不在是原生的response了,这里不就是对应了文章开头的第二点

那么我们从源码的角度重新梳理一下文章开头的两者区别:
1.实例化Request并返回
2.捕获所有ApiException
3.进行了权限认证
4.处理了response

总结:

这四个模块都在一个请求周期里得到了体现,但实际上又各有乾坤,讲到这里DRF是怎样把他们加到请求周期,实现了自己的新特性,是不是有一种醍醐灌顶的感觉,至于APIView的dispatch相对还多了一些其他的方法,实质上都是为了这4个模块服务的