Django-rest-framework源码分析(一)
一、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(必须用关键字传参的形式)。
Django-rest-framework源码分析(一)的更多相关文章
- Django rest framework源码分析(3)----节流
目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...
- Django rest framework源码分析(1)----认证
目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...
- Django rest framework 源码分析 (1)----认证
一.基础 django 2.0官方文档 https://docs.djangoproject.com/en/2.0/ 安装 pip3 install djangorestframework 假如我们想 ...
- Django rest framework源码分析(一) 认证
一.基础 最近正好有机会去写一些可视化的东西,就想着前后端分离,想使用django rest framework写一些,顺便复习一下django rest framework的知识,只是顺便哦,好吧. ...
- Django rest framework源码分析(4)----版本
版本 新建一个工程Myproject和一个app名为api (1)api/models.py from django.db import models class UserInfo(models.Mo ...
- Django rest framework源码分析(2)----权限
目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...
- 3---Django rest framework源码分析(3)----节流
Django rest framework源码分析(3)----节流 目录 添加节流 自定义节流的方法 限制60s内只能访问3次 (1)API文件夹下面新建throttle.py,代码如下: # u ...
- Django之REST framework源码分析
前言: Django REST framework,是1个基于Django搭建 REST风格API的框架: 1.什么是API呢? API就是访问即可获取数据的url地址,下面是一个最简单的 Djang ...
- Django Rest Framework源码剖析(八)-----视图与路由
一.简介 django rest framework 给我们带来了很多组件,除了认证.权限.序列化...其中一个重要组件就是视图,一般视图是和路由配合使用,这种方式给我们提供了更灵活的使用方法,对于使 ...
- Django Rest Framework源码剖析(三)-----频率控制
一.简介 承接上篇文章Django Rest Framework源码剖析(二)-----权限,当服务的接口被频繁调用,导致资源紧张怎么办呢?当然或许有很多解决办法,比如:负载均衡.提高服务器配置.通过 ...
随机推荐
- 没有图片的freemarker下载,备份
没有图片的freemarker下载,备份 //以下代码也可以使用/* public String exportApproveCase(@PathVariable("proId") ...
- Samtec 5G探索之路
序言:时代在发展,2020年5G作为元年.5G全程第五代移动通信技术(英语:5th generation mobile networks或5th generation wireless systems ...
- 压力测试(八)-多节点JMeter分布式压测实战
1.Jmeter4.0分布式压测准备工作 简介:讲解Linux服务器上jmeter进行分布式压测的相关准备工作 1.压测注意事项 the firewalls on the systems are tu ...
- 进阶之路 | 奇妙的Handler之旅
前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 需要已经具备的知识: Handler的基本概念及使用 学习导图: 一.为什么要学习Handler? 在Andr ...
- 一篇带你看懂Flutter叠加组件Stack
注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 Stack Stack组件可以将子组件叠加显示,根据子组件 ...
- 一些大厂的css reset 代码
不同的浏览器对标签的默认值不同,为了避免页面出现浏览器差异,所以要初始化样式表属性.使用通配符*并不可取,因为会遍历到每一个标签,大型网页会加载过慢,影响性能. 雅虎工程师提供的CSS初始化示例代码: ...
- java异常和throw和throws的区别
之前在编程中编译完成后,运行时,会遇见一些常见的错误,如NullPointerException,ArrayIndexOutOfBoundsException等等 在今天重新回顾学习了java异常,总 ...
- 关于使用Binlog和canal来对MySQL的数据写入进行监控
先说下Binlog和canal是什么吧. 1.Binlog是mysql数据库的操作日志,当有发生增删改查操作时,就会在data目录下生成一个log文件,形如mysql-bin.000001,mysql ...
- 进程,线程,Event Loop(事件循环),Web Worker
线程,是程序执行流的最小单位.线程可与同属一个进程的其他线程共享所拥有的全部资源,同一进程中的多个线程之间可以并发执行.线程有就绪,阻塞,运行三种基本状态. 阮一峰大神针对进程和线程的类比,很是形象: ...
- ubuntu下使用apt-get install安装软件的安装位置
在ubuntu下使用 apt-get install 或 apt install 下载安装软件,软件下载及安装后的目录.: A.下载的软件的存放位置:/var/cache/apt/archives B ...

