ymfx
一、APIView
入口
在路由层执行as_view()方法
rest-framework/views.py/class APIView/def as_view()

可以看到,APIView继承了Django原生的View,并且重写了as_view()方法,在APIView的as_view方法中,除了一处类中是否有queryset属性的判定,as_view主要实现的功能是将原来返回的函数对象view加入装饰器装饰,使之可以被csrfmiddleware中间件的校验忽略,因为我们无法从前端获取csrf_token。如果不采用这种方法,我们不得不禁用该中间件,这就影响了我们继续正常使用Django原生框架。
django/views/base.py/class View/def as_view()

在Django原生的View类的as_view方法中,返回的函数对象view是一个闭包函数,该函数被装饰器csrf_exempt装饰后返回到路由层,在路由层被执行,在执行view时,view返回的是dispatch方法执行的结果。
在APIView类中重写了dispatch方法,所以上图红框内执行的是APIView的dispatch方法。
rest-framework/views.py/class APIView/def dispatch()

rest-framework/views.py/class APIView/def initialize_request()

该方法返回了一个Request对象,Request类是一个restframework对Django原生的request进行封装的类,它保留了原生的request对象,作为新实例化request对象的_request属性,并且拥有原生的request对象的所有属性和方法。
rest-framework/views.py/class APIView/def dispatch()

回到dispatch方法,这里的if判断利用了反射,将我们自己写的get,post等方法取出,且让变量handle指向该方法。self.http_mehtod_names是一个列表,其中包含HTTP八个请求名称的字符串(['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'])。
rest-framework/views.py/class APIView/def finalize_response()

我们看到,在finalize_response函数中,传入了response参数,并且对其进行了一些封装,加入了属性,以及用断言进行校验。
response是handle调用后返回的结果,handle则是我们自己写的对应HTTP请求的方法,我们在方法中最后返回了一个HttpResponse对象。在dispatch方法中,主要是用反射,对HTTP请求的类型进行对应方法的分发。
二、Request类
rest-framework/request.py/class Request

可以看到,Django原生的request对象被作为参数传入,封装进了restframework Request类实例化对象的_request属性中,在实例化时,还给新的Request对象加入了新的属性和方法。其中Empty是一个用来占位的空白类。
当我们想执行Django原生的request对象的方法或者想要获取原生request对象的属性时,在class Request中重写了__getattr__(self,attr)方法,该魔法方法在对象获取属性时,当该对象找不到属性时执行。
rest-framework/request.py/class Request/def __getattr()__

当新request对象的属性或者方法不存在时,在原生的request对象中寻找,如果也不存在,会抛一个AttributeError异常,这里做了异常捕获后,交给__getattribute__()去执行。在Response中没有重写__getattribute__()方法,当属性不存在时,重写的__getattr__截获了属性查找,如果_request仍然没有找到该属性,就要交给新式类自己的__getattribute__去执行,以保证该类的属性查找正常运行。
三、Serializer
restframework/serializers.py/class Serializer
Serializer类继承了BaseSerializer,并且没有重写__init__和__new__方法,所以当该类实例化产生对象的时候,调用的是父类BaseSerializer的__init__和__new__方法。
restframework/serializers.py/class BaseSerializer

先执行__new__方法,实例化一个空对象,在实例化对象的时候,有可能以关键字传参的形式传入many参数,该参数在__new__方法中被**kwargs接受,放入字典中。
__new__中的if判断是将many取出,当many的Boolean值为false或者many参数没有传入的时候,不执行if下面的语句,也就是会正常实例化一个对象,__new__并未对对象的创建过程做拦截。如果many中有值并且其Boolean不为false时,会执行many_init方法。
restframework/serializers.py/class BaseSerializer/def many_init()
在执行many_init方法时,返回的是一个ListSerializer对象。具体执行过程已经在图上标出。
将QuerySet对象而不是数据对象作为参数,进行序列化时,必须写many=True(必须用关键字传参的形式)。
ymfx的更多相关文章
- 浅聊标签<include>和<viewStub>
在开发中我们往往会遇到这种情况,当一个布局文件比较复杂时,我们一个劲地往里面拖各种控件button,textView,imageView阿等等,等过了一段时间后,出现bug,自己都把自己搞懵比啦,特别 ...
随机推荐
- 使用<script>标签在HTML网页中插入JavaScript代码
新朋友你在哪里(如何插入JS) 我们来看看如何写入JS代码?你只需一步操作,使用<script>标签在HTML网页中插入JavaScript代码.注意, <script>标签要 ...
- HttpWebRequest请求返回非200的时候 HttpWebResponse怎么接受返回错误提示
当我们使用HttpWebRequest发送请求的时候如果服务器返回的不是200状态,那么请求代码肯定会异常,其实请求和返回并没有什么异常,只是.net内部就认定了 返回的不要是200 就是异常 那么我 ...
- js 本地预览图片和得到图片实际大小
//填充预览图片 function adpter(file, upfile) { var imgName = new Date().getTime() + file.name.substr(file. ...
- C++: string copy-on-write
https://blog.csdn.net/haoel/article/details/24058 https://www.cnblogs.com/promise6522/archive/2012/0 ...
- drop database出现1010
> drop database glc; ERROR (HY000): Error dropping database (can't rmdir './glc/', errno: 17) Fri ...
- colormap 参数及对应色卡
[参考] [1]matlab帮助文档
- VS2010-MFC(图形图像:CDC类及其屏幕绘图函数)
转自:http://www.jizhuomi.com/software/244.html 上一节讲了文本输出的知识,本节的主要内容是CDC类及其屏幕绘图函数. CDC类简介 CDC类是一个设备上下文类 ...
- HTTP协议请求篇
http协议的基本概念 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.是工作在tcp/ip协议基础上的,所有的WWW文件都必须 ...
- 20.multi_case05
#coding:utf-8 # 通过gather方法 import asyncio async def a(t): print('-->', t) await asyncio.sleep(0.5 ...
- Maven使用初步
一.安装: 1.下载:http://maven.apache.org/download.cgi 2.设置环境变量 1.创建"M2_HOME",值为Maven安装路径(如:D:\Ja ...

