DRF请求的生命周期
作为一个工作3年左右的码农,在各种框架的摸爬滚打中,我也接触了不少前端后端的技术栈,其中DRF算是我后端日常工作中的用得最多的框架。今天就简单聊聊DRF请求的生命周期。由于篇幅原因,我在此篇文章中只是稍作解析,后续针对各部分会单独写文章来详细讲解相关源码的执行过程以及如何改编源码。
drf中请求的生命周期:
1、django接收请求后,先进行中间件的process_request方法,进行路由匹配后再进行中间件的process_view方法;
class MiddlewareMixin:
# 中间件源码,当有请求进来时,会自动执行中间件的call方法;
# 一般我们自定义中间件都是重写process_request和process_view方法
# 从源码中可看出执行顺序:
def __call__(self, request):
# Exit out to async mode, if needed
if asyncio.iscoroutinefunction(self.get_response):
return self.__acall__(request)
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
response = response or self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response
2、再执行APIView类中的as_view方法获取view函数,并同时免除了csrf认证(闭包原理)
class APIView(View):
# 简略版源码:
@classmethod
def as_view(cls, **initkwargs):
view = super().as_view(**initkwargs) # 调用原Django框架的as_view方法获取view函数
view.cls = cls
view.initkwargs = initkwargs
return csrf_exempt(view)
# 原Django框架的as_view方法:
class View:
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs)
self.setup(request, *args, **kwargs)
return self.dispatch(request, *args, **kwargs) # 调用dispatch函数
view.view_class = cls
view.view_initkwargs = initkwargs
return view
3、通过路由匹配执行view函数,并在view中调用dispatch函数。
class APIView(View):
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# request封装
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try: # 捕获异常
self.initial(request, *args, **kwargs) # 版本管理、认证。权限、限流组件执行
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
4、在dispatch中进行版本管理、request封装、认证、权限、限流处理
# 版本管理
def initial(self, request, *args, **kwargs):
self.format_kwarg = self.get_format_suffix(**kwargs)
version, scheme = self.determine_version(request, *args, **kwargs) # 执行versioning_class中的determine_version方法,获取version和scheme
request.version, request.versioning_scheme = version, scheme # 封装参数到request中
# Ensure that the incoming request is permitted
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
# request封装
def initialize_request(self, request, *args, **kwargs):
parser_context = self.get_parser_context(request)
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
#认证
def _authenticate(self):
for authenticator in self.authenticators:
try:
user_auth_tuple = authenticator.authenticate(self) # 执行authenticate方法进行具体的认证流程
except exceptions.APIException:
self._not_authenticated()
raise
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple # 将返回值进行封装
return
self._not_authenticated()
# 权限
def check_permissions(self, request):
for permission in self.get_permissions():
if not permission.has_permission(request, self): # 多个权限类中有一个方法为False则报错并抛出异常
self.permission_denied(
request,
message=getattr(permission, 'message', None),
code=getattr(permission, 'code', None)
)
# 限流
def check_throttles(self, request):
throttle_durations = []
for throttle in self.get_throttles(): # 循环执行各限流类中的方法
if not throttle.allow_request(request, self):
throttle_durations.append(throttle.wait()) # 限流方法返回False则将等待时间加到列表中
if throttle_durations:
durations = [
duration for duration in throttle_durations
if duration is not None
]
duration = max(durations, default=None) # 取列表中的最大等待时间
self.throttled(request, duration) # 抛出异常
5、执行具体的视图函数并返回数据
6、执行中间件的process_response方法并返回数据到客户端
以上只是简单分析了一下执行流程,涉及到的源码都是为了方便理解而经过简化的,只供参考。每个组件源码的设计思路和执行流程其实都有一定的复杂度,对于各个组件的源码,我在接下来的日子中也会逐一进行详细剖析。
DRF请求的生命周期的更多相关文章
- Minor【 PHP框架】2.第一个应用与请求的生命周期
框架Github地址:github.com/Orlion/Minor (如果觉得还不错给个star哦(^-^)V) 框架作者: Orlion 知乎:https://www.zhihu.com/peop ...
- Mvc请求的生命周期
ASP.NET Core : Mvc请求的生命周期 translation from http://www.techbloginterview.com/asp-net-core-the-mvc-req ...
- [oldboy-django][2深入django]django一个请求的生命周期 + WSGI + 中间件
1 WSGI # WSGI(是一套协议,很多东西比如wsgiref, uwsgiref遵循这一套协议) - django系统本质 别人的socket(wsgiref或者uwsgiref) + djan ...
- Djngo 请求的生命周期
1.Django请求的生命周期 路由系统 -> 试图函数(获取模板+数据=>渲染) -> 字符串返回给用户 2.路由系统 /index/ -> 函数或类.as_view() / ...
- 05.Django-form表单与请求的生命周期
Django中请求的生命周期 HTTP请求及服务端响应中传输的所有数据都是字符串 步骤 用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务器 url经过wsgi和中间件,到达路由映射表,在 ...
- Envoy 代理中的请求的生命周期
Envoy 代理中的请求的生命周期 翻译自Envoy官方文档. 目录 Envoy 代理中的请求的生命周期 术语 网络拓扑 配置 高层架构 请求流 总览 1.Listener TCP连接的接收 2.监听 ...
- JDK HttpClient 单次请求的生命周期
HttpClient 单次请求的生命周期 目录 HttpClient 单次请求的生命周期 1. 简述 2. uml图 3. Http连接的建立.复用和降级 3.1 调用流程及连接的建立和复用 3.2 ...
- Django中请求的生命周期
1. 概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串. 在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中. Django的请求生命周期是指当用户 ...
- django请求的生命周期
1. 概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串. 在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中. Django的请求生命周期是指当用户 ...
- [ Laravel 5.5 文档 ] 底层原理 —— 一次 Laravel 请求的生命周期
Posted on 2018年3月5日 by 学院君 简介 当我们使用现实世界中的任何工具时,如果理解了该工具的工作原理,那么用起来就会得心应手,应用开发也是如此.当你理解了开发工具如何工作,用起 ...
随机推荐
- vue项目之主页布局
1.背景 2.基本结构 代码: <template> <el-container class="home-container"> <!-- 头部--& ...
- 字符串系列目录&&说明
字符串准备写成一个系列. 目录 \(\text{KMP笔记}\) \(\text{Manacher笔记}\) [] [] [] 格式与说明 下面的说明和格式将被应用于整个系列. 说明 所有字符串的下标 ...
- 增强用户体验:2个功能强大的.NET控制台应用帮助库
前言 对于.NET开发者而言,构建控制台应用程序时,如何提升用户交互的流畅性和满意度,是一个持续探索与优化的话题.今天大姚给大家分享2个功能强大的.NET控制台应用帮助库,希望可以帮助大家能够快速的构 ...
- SenseCraft 部署模型到Grove Vision AI V2图像处理模块
Grove Vision AI V2 图像处理模块开箱测评 摘要 今天教大家快速上手 Grove Vision AI V2 图像处理模块,我们将一起探讨如何利用 SenseCraft 部署 AI 模型 ...
- python学习(一)django orm多表查询
###多表查询 一般的多表查询都是直接建立一个多对多关系 class Books(models.Model): users = models.ManyToManyField(User, related ...
- C# JSON序列化指定名称
今天在做项目时遇到了要将json对象序列化为数据库表, 结果数据库表和json对象数据类型和字段名称对不上.于是就有了一下的解决方案: 需要转化的对象 { "orgAccountId&qu ...
- 折腾 Quickwit,Rust 编写的分布式搜索引擎 - 从不同的来源摄取数据
摄取 API 在这节教程中,我们将介绍如何使用 Ingest API 向 Quickwit 发送数据. 要跟随这节教程,您需要有一个本地的 Quickwit 实例正在运行. https://quick ...
- JVM学习第二篇思考:一个Java代码是怎么运行起来的-下篇
JVM学习第二篇思考:一个Java代码是怎么运行起来的-下篇 在上一篇<JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇>中咱们知道类一个Java类的生命周期需要经历以下七个阶 ...
- 填坑 Plugin 'mysql_native_password' is not loaded
数据库从 mysql5.7 升级到 mysql8.4,部分场景出现以下错误提示:Plugin 'mysql_native_password' is not loaded 原因是:mysql_nativ ...
- FastGPT 正式接入 Flux,准备好迎接 AI 绘画的狂风了么?
Flux 大家最近都听说了吧?它是一款新推出的 AI 绘画模型,拳打 Stable Diffusion 3,脚踢 Midjourney,整个 AI 绘画界都沸腾了. Flux 的主创团队来自由 Sta ...