一、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的更多相关文章

  1. 浅聊标签<include>和<viewStub>

    在开发中我们往往会遇到这种情况,当一个布局文件比较复杂时,我们一个劲地往里面拖各种控件button,textView,imageView阿等等,等过了一段时间后,出现bug,自己都把自己搞懵比啦,特别 ...

随机推荐

  1. iOS进阶一OC对象的本质

    OC对象的本质 平时编写的Object-C代码,底层实现其实都是C/C++代码. 所以Objective-C的面向对象都是基于C/C++的数据结构实现的,OC对象内部可以容纳不同数据类型的数据,因此可 ...

  2. iOS开发系列-Shell脚本编译SDK

    Library静态库Shell脚本 #!/bin/bash #要build的target名 target_Name="IFlyMSC" #编译模式 Release.Debug bu ...

  3. php数组的快速排序

    function quick($array){ if(count($array)<=1){ return $array; } $key=$array[0]; $right=array(); $l ...

  4. thinkphp 运算符

    我们可以对模板输出使用运算符,包括对“+”“ –” “*” “/”和“%”的支持. 大理石平台厂家 例如: 运算符 使用示例 + {$a+$b} - {$a-$b} * {$a*$b} / {$a/$ ...

  5. thinkphp 变量输出

    在模板中输出变量的方法很简单,例如,在控制器中我们给模板变量赋值: 大理石平台支架 $name = 'ThinkPHP'; $this->assign('name',$name); $this- ...

  6. CF Round #427 (Div. 2) C. Star sky [dp]

    题目链接就长这样子? time limit per test 2 seconds memory limit per test 256 megabytes   Description The Carte ...

  7. 微软RPC官方教程

    http://msdn.microsoft.com/en-us/library/windows/desktop/aa379010(v=vs.85).aspx 注意:原文版本较老,我更新和改变了部分内容 ...

  8. System.IO.Directory.cs

    ylbtech-System.IO.Directory.cs 1.返回顶部 1. #region 程序集 mscorlib, Version=4.0.0.0, Culture=neutral, Pub ...

  9. LANMP相关配置

    Linux Apache Mysql Postgresql 安装 yum -y install httpd yum -y install mysql mysql-server yum -y insta ...

  10. idea激活破解

    下载链接:https://pan.baidu.com/s/1BADk1MCm0YxtB6zoX0DivA 提取码 ze9m将破解补丁放到bin文件中jetbrains-all.jar 在这俩个文件最后 ...