django-rest-framework-源码解析001-整体框架
简介
Django Rest Framework是一个强大且灵活的工具包,主要用以构建RESTful风格的Web API。
Django REST Framework(简称DRF)可以在Django的基础上迅速实现API,并且自身还带有 基于WEB的测试和浏览页面,可以方便的测试自己的API。DRF几乎是Django生态中进行前后端 分离开发的默认库。
Django REST Framework具有以下功能和特性:
- 自带基于Web的可浏览的API,对于开发者非常有帮助
- 支持OAuth1a 和OAuth2认证策略
- 支持ORM或非ORM数据源的序列化
- 高可自定制性,多种视图类型可选
- 自动生成符合 RESTful 规范的 API 支持
- OPTION、HEAD、POST、GET、PATCH、PUT、DELETE等HTTP方法
- 根据 Content-Type 来动态的返回数据类型(如HTML、json)
- 细粒度的权限管理(可到对象级别)
- 丰富的文档和强大的社区支持
- Mozilla、Red Hat、 Heroku和Eventbrite等知名公司正在使用
安装
在项目环境中直接pip安装
pip install djangorestframework
安装完毕,在项目配置文件中,注册app:
INSTALLED_APPS = (
...
'rest_framework',
)
如果你想使用基于浏览器的可视化的API目录,并且希望获得一个登录登出功能,那么可以在根 路由下添加下面的路由('api-auth/' 可以随意指定),这个功能类似Django自带的admin后台:
urlpatterns = [
...
path('api-auth/', include('rest_framework.urls'))
]
为了登录操作,也许你还要生成数据表,创建超级用户。
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
DRF模块
DRF有几大功能模块:
1. 序列化模块(Serializer): (rest_framework.serializers) 对数据进行序列化和反序列化, 序列化即通过django的model对象创建序列化对象, 进而将对应的字段转换为json格式, 反序列化即通过请求中的json数据创建反序列化对象, 进而将json数据转化为字典格式, 序列化模块中提供了常用的三种序列化类:
1.1 Serializer类(rest_framework.serializers.Serializer): 基础的序列化类, 需要自己编写所有的字段以及create和update方法,比较底层,抽象度较低
1.2 ModelSerializer类(rest_framework.serializers.ModelSerializer): 更常用的序列化类, 不需要手动编写所有字段, 会根据指向的model自动生成默认的字段和简单的create和update方法
1.3 ListSerializer类(rest_framework.serializers.ListSerializer): 当使用ModelSerializer进行群改(一次更新多个model对象)时, 需要用到ListSerializer并重写update()方法
2. 请求模块(Request): (rest_framework.request.Request) 对django的原生request对象进行二次封装, 将原生request对象封装至DRF自己的Request的_request属性中, 并新增了解析器, 认证器等属性
3. 解析模块(Parses) : (rest_framework.parser) 对request中携带的常见Content-Type进行相应的解析:
3.1 JSONParser类(rest_framework.parser.JSONParser): 解析Content-Type为 application/json 的数据
3.2 FormParser类(rest_framework.parser.FormParser): 解析Content-Type为 application/x-www-form-urlencoded 的数据(普通form表单提交的数据)
3.3 MultiPartParser类(rest_framework.parser.MultiPartParser): 解析Content-Type为 multipart/form-data 的数据(比普通form表单支持的类型更多)
3.4 FileUploadParser类(rest_framework.parser.FileUploadParser): 解析Content-Type为 */* 的数据, 一般为文件类型的数据
4. 认证模块(Authentication): (rest_framework.authentication) 对request进行验证, 判断请求的用户是否合法, 一般将用户分成三类: 游客(不携带认证信息的匿名用户), 非法用户(携带了认证信息的用户但信息是错误的), 合法用户(携带了正确的认证信息)
5. 权限模块(Permission): (rest_framework.permission) 对通过认证的用户判断其是否有权限访问该页面
6. 频率模块(Throttle): (rest_framework.throttling) 限制同一个访问客户端的IP或用户等指标每秒访问服务器的次数
7. 响应模块(Response): (rest_framework.response) 将序列化后的数据以及其他常见response数据如http状态码/headers等封装成Response对象
8. 异常模块(Exception): (rest_framework.exceptions) 捕获认证模块/权限模块/频率模块/自定义视图类/响应模块中所抛出的异常, 并将异常信息转化为json返回给前端
9. 渲染模块(Renders): (rest_framework.renderers) 返回json数据还是将数据渲染为HTML页面等
DRF源码入口
rest_framework.views.as_view()
使用DRF时, 需要将视图文件(view.py)定义的类(CBV)继承rest_framework的APIView(APIView是django原生View的子类)或者将定义的函数(FBV)用rest_framework的api_view装饰器进行装饰. 因此在url中调用的view.as_view()方法或者api_view中调用的as_view方法就是rest_framework.views.as_view()方法, 即rest_framework重写了django原生的view中的as_view()方法
@classmethod
def as_view(cls, **initkwargs):
"""
Store the original class on the view function. This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
"""
代码省略......# 1.调用父类View的as_view
view = super().as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs # 2.跳过csrf认证
# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
分析as_view()方法, 发现其主要做了两件事: 1. 调用父类View的as_view 2. 跳过csrf认证
因此主要的逻辑还是在父类View的as_view中, 来到父类View.as_view的代码, 发现其定义了一个view方法, 最后返回这个view方法, 在view方法中实例化了一个cls的对象(self), 然后返回了self.dispatch方法的返回值
@classonlymethod
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
代码省略......
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.setup(request, *args, **kwargs)
if not hasattr(self, 'request'):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
return self.dispatch(request, *args, **kwargs)
代码省略......return view
rest_framework.views.dispatch()
注意上面的cls就是as_view的cls参数, 也就是外层APIView中的as_view的cls参数, 也就是APIView, 那么这里cls创建的self就是APIView的对象, 那么调用的dispatch方法就是APIView对象的dispatch方法, 如果我们自定义的视图类没有重写dispatch方法, 那么就会走APIView的dispatch方法, 可以看到APIView中确实重写了dispatch方法, 这里就是DRF的核心入口
def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs # 请求模块/解析模块
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate? try:
# 三大认证模块
self.initial(request, *args, **kwargs) # 通过反射获取自定义视图类中request.method对应的方法
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed # 响应模块
response = handler(request, *args, **kwargs) except Exception as exc:
# 异常处理模块
response = self.handle_exception(exc) # 渲染模块
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
在这个dispatch中主要分为了5部分
1. request = self.initialize_request(request, *args, **kwargs) 这里初始化了一个DRF的Request对象, 除了包括了django原生request, 还包括了解析器, 权限器等
2. self.initial(request, *args, **kwargs) 这里是对Request进行三大校验, 包括认证模块(authentication), 权限模块(permission), 频率模块(throttle)
3. response = handler(request, *args, **kwargs) 这里是先通过反射机制获取自定义视图类中request.method对应的方法, 然后调用该方法, 得到处理结果
4. response = self.handle_exception(exc) 这里是捕获三大校验和获取响应所抛出的异常, 并得到异常的处理结果
5. self.response = self.finalize_response(request, response, *args, **kwargs) 这里将上面的到的正常或异常处理结果(response)再进行最终的渲染处理, 可以渲染为单纯的json数据或者是方便浏览器查看的html格式等
django-rest-framework-源码解析001-整体框架的更多相关文章
- Django Rest Framework源码剖析(八)-----视图与路由
一.简介 django rest framework 给我们带来了很多组件,除了认证.权限.序列化...其中一个重要组件就是视图,一般视图是和路由配合使用,这种方式给我们提供了更灵活的使用方法,对于使 ...
- Django Rest Framework源码剖析(三)-----频率控制
一.简介 承接上篇文章Django Rest Framework源码剖析(二)-----权限,当服务的接口被频繁调用,导致资源紧张怎么办呢?当然或许有很多解决办法,比如:负载均衡.提高服务器配置.通过 ...
- [源码解析] 并行分布式框架 Celery 之架构 (1)
[源码解析] 并行分布式框架 Celery 之架构 (1) 目录 [源码解析] 并行分布式框架 Celery 之架构 (1) 0x00 摘要 0x01 Celery 简介 1.1 什么是 Celery ...
- [源码解析] 并行分布式框架 Celery 之架构 (2)
[源码解析] 并行分布式框架 Celery 之架构 (2) 目录 [源码解析] 并行分布式框架 Celery 之架构 (2) 0x00 摘要 0x01 上文回顾 0x02 worker的思考 2.1 ...
- [源码解析] 并行分布式框架 Celery 之 worker 启动 (1)
[源码解析] 并行分布式框架 Celery 之 worker 启动 (1) 目录 [源码解析] 并行分布式框架 Celery 之 worker 启动 (1) 0x00 摘要 0x01 Celery的架 ...
- [源码解析] 并行分布式框架 Celery 之 worker 启动 (2)
[源码解析] 并行分布式框架 Celery 之 worker 启动 (2) 目录 [源码解析] 并行分布式框架 Celery 之 worker 启动 (2) 0x00 摘要 0x01 前文回顾 0x2 ...
- [源码解析] 并行分布式框架 Celery 之 容错机制
[源码解析] 并行分布式框架 Celery 之 容错机制 目录 [源码解析] 并行分布式框架 Celery 之 容错机制 0x00 摘要 0x01 概述 1.1 错误种类 1.2 失败维度 1.3 应 ...
- AspNetCore3.1_Secutiry源码解析_8_Authorization_授权框架
目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心流程 AspNetCore3.1_Se ...
- [源码解析] 并行分布式框架 Celery 之 Lamport 逻辑时钟 & Mingle
[源码解析] 并行分布式框架 Celery 之 Lamport 逻辑时钟 & Mingle 目录 [源码解析] 并行分布式框架 Celery 之 Lamport 逻辑时钟 & Ming ...
- django之admin源码解析
解析admin的源码 第一步:项目启动,加载settings文件中的 INSTALLED_APPS 里边有几个app就加载几个,按照注册顺序来执行. 第二步:其中加载的是admin.py,加载每一个a ...
随机推荐
- 黎活明8天快速掌握android视频教程--19_采用ListView实现数据列表显示
1.首先整个程序也是采用mvc的框架 DbOpenHelper 类 package dB; import android.content.Context; import android.databas ...
- 微信小程序上传Word文档、PDF、图片等文件
<view class="main" style="border:none"> <view class="title"&g ...
- 内存节省机制C演示
编写代码实质是通过指令对计算机内存进行操作,计算机的硬件设备往往十分有限,尤其是内存.如何使有限的存储空间利用效率达到最大,成为了代码优化首先要考虑的事情. 比如,输入三个数比较大小并输出最小值.下面 ...
- Idea中SpringBoot整合JSP
最近在学习SpringBoot,看到SpringBoot整合jsp,顺带记录一下. 1.创建一个SpringBoot项目 点击Next 注意:packaging选中War,点击Next Webà选中W ...
- 一不小心,我就上传了 279674 字的 MySQL 学习资料到 github 上了
自从2019年11月我们出版了<千金良方--MySQL 性能优化金字塔法则>一书之后,持续不断有人来询问我MySQL 4 个系统字典库相关的问题,因为篇幅原因,书中并没有完整收录4个字典库 ...
- 学习前端的时候,突然想起了Sharepoint母版页里的占位符,算知识的融会不?
今天看到这个段话,我就想起来当时学习Sharepoint的时候,总是搞不明白我们老师讲的那个母版页里的占位符到底是干啥的.现在看到了类似的东西,让我想起来了之前一直搞不懂的东西,很感慨. (完)
- node 模块正确暴露方法
一个node模块,为了能够服用,就需要将其暴露,那么如何正确写呢?(参考:https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/Expr ...
- SQL循环遍历,删除表里某一列是重复的数据,只保留一条。
DECLARE @tempId NVARCHAR(Max), @tempIDD uniqueidentifier WHILE EXISTS ( SELECT UserId FROM Users Gro ...
- 使用Visual Studio 开发SharePoint项目时的快捷键
组合键:ctrl+c,alt+c,Shift+ctrl+c,可以快速的将文件拷贝到对应的部署目录下.
- springboot集成springDataJpa
1.引用依赖 <!--spring-data-jpa--> <dependency> <groupId>org.springframework.boot</g ...