一、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开发系列-打印内存地址

    打印内存地址 基本数据类型 定义一个基本数据类型,会根据变量类型分配对应的内存空间.比如定义一个int类型的变量a. int a = 10; 内存如下 输入变量a在内存中内存地址 NSLog(@&qu ...

  2. .net 接受请求过来的流

    //接收POST过来的数据 System.IO.Stream s = Request.InputStream; int count = 0; byte[] buffer = new byte[1024 ...

  3. lock tables和unlock tables

    1.lock tables table1 read,table2 read,table3 read igoodful@a8-apple-iphone-db00.wh(glc) > show ta ...

  4. 关于TMDS

    https://en.wikipedia.org/wiki/Transition-minimized_differential_signaling TMDS,Transition Minimized ...

  5. 【BZOJ2298】【luoguP2519】problem a

    description 一次考试共有n个人参加,第i个人说:"有ai个人分数比我高,bi个人分数比我低."问最少有几个人没有说真话(可能有相同的分数) analysis 这题转化模 ...

  6. rancher v2.2.4创建kubernetes集群出现[etcd] Failed to bring up Etcd Plane: [etcd] Etcd Cluster is not healthy

    主机:rancher(172.16.2.17),master(172.16.2.95),node01(172.16.2.234),node02(172.16.2.67) 问题:开始是用的rancher ...

  7. Android Matrix理论与应用详解

    转:http://zensheno.blog.51cto.com/2712776/513652 Matrix学习——基础知识 以前在线性代数中学习了矩阵,对矩阵的基本运算有一些了解,前段时间在使用GD ...

  8. 命令学习_IPCONFIG: DNS cache操作

    IPCONFIG: DNS cache操作 Windows会将解析到的DNS信息缓存,这个机制可以加速重复的域名访问.从DNS Server返回的DNS Response消息中带有"Time ...

  9. SpringCloud学习笔记(八):Zuul路由网关

    概述 是什么? Zuul包含了对请求的路由和过滤两个最主要的功能: 其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请 ...

  10. linux nload命令简介及安装方法

    第一步:nload命令简介 nload 命令用于查看linux网络流量状况,实时输出.可以理解为是一个控制台应用程序,用来实时监测网络流量和带宽使用情况的命令. 使用可视化的界面显示流入和留出系统的网 ...