作为一个工作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请求的生命周期的更多相关文章

  1. Minor【 PHP框架】2.第一个应用与请求的生命周期

    框架Github地址:github.com/Orlion/Minor (如果觉得还不错给个star哦(^-^)V) 框架作者: Orlion 知乎:https://www.zhihu.com/peop ...

  2. Mvc请求的生命周期

    ASP.NET Core : Mvc请求的生命周期 translation from http://www.techbloginterview.com/asp-net-core-the-mvc-req ...

  3. [oldboy-django][2深入django]django一个请求的生命周期 + WSGI + 中间件

    1 WSGI # WSGI(是一套协议,很多东西比如wsgiref, uwsgiref遵循这一套协议) - django系统本质 别人的socket(wsgiref或者uwsgiref) + djan ...

  4. Djngo 请求的生命周期

    1.Django请求的生命周期 路由系统 -> 试图函数(获取模板+数据=>渲染) -> 字符串返回给用户 2.路由系统 /index/ -> 函数或类.as_view() / ...

  5. 05.Django-form表单与请求的生命周期

    Django中请求的生命周期 HTTP请求及服务端响应中传输的所有数据都是字符串 步骤 用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务器 url经过wsgi和中间件,到达路由映射表,在 ...

  6. Envoy 代理中的请求的生命周期

    Envoy 代理中的请求的生命周期 翻译自Envoy官方文档. 目录 Envoy 代理中的请求的生命周期 术语 网络拓扑 配置 高层架构 请求流 总览 1.Listener TCP连接的接收 2.监听 ...

  7. JDK HttpClient 单次请求的生命周期

    HttpClient 单次请求的生命周期 目录 HttpClient 单次请求的生命周期 1. 简述 2. uml图 3. Http连接的建立.复用和降级 3.1 调用流程及连接的建立和复用 3.2 ...

  8. Django中请求的生命周期

    1. 概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串. 在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中. Django的请求生命周期是指当用户 ...

  9. django请求的生命周期

    1. 概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串. 在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中. Django的请求生命周期是指当用户 ...

  10. [ Laravel 5.5 文档 ] 底层原理 —— 一次 Laravel 请求的生命周期

     Posted on 2018年3月5日 by  学院君 简介 当我们使用现实世界中的任何工具时,如果理解了该工具的工作原理,那么用起来就会得心应手,应用开发也是如此.当你理解了开发工具如何工作,用起 ...

随机推荐

  1. js 实现俄罗斯方块(二)

    上篇已经看过整个游戏的样子了,本节我们来分析下整个游戏 和实现的逻辑! 首先看下游戏规则: 首先确定这几个形状原型   这7个基础图形都是由4个格子组成. 规则: 1.当所有色块填满一整行以后自动清理 ...

  2. AtCoder Beginner Contest 311

    Toyota Programming Contest 2023#4(AtCoder Beginner Contest 311) A - First ABC (atcoder.jp) 记录一下\(ABC ...

  3. 牛客周赛 Round 7

    牛客周赛 Round 7 A-游游的you矩阵_牛客周赛 Round 7 (nowcoder.com) 把四种字符凑一起看看有没有\(y,o,u\)就行 #include <bits/stdc+ ...

  4. 第 356 场周赛 - 力扣(LeetCode)

    第 356 场周赛 - 力扣(LeetCode) 2798. 满足目标工作时长的员工数目 - 力扣(LeetCode) 一次遍历 class Solution { public: int number ...

  5. 快手 内推码:TYORVzmsw 秋招 应届生/实习生 真正本人内推 已有多人在我内推之后,接连顺利通过了HR筛选、用人部门筛选、面试!

    内推码:TYORVzmsw 校园招聘岗位列表:https://campus.kuaishou.cn/#/campus/jobs?code=TYORVzmsw 真正的本人内部推荐! 已有多人在我内推之后 ...

  6. RabbitMQ接口封装

    1.引用 <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client< ...

  7. C 语言多文件编译

    C 语言中的多文件编程通常涉及将代码分散在几个不同的源文件(.c 文件)和头文件(.h 文件)中.这么做可以帮助你组织大型项目,提高代码的重用性,便于团队合作,分离接口和实现,以及加快编译时间.下面是 ...

  8. 【测试平台开发】——05Flask后端api开发实战(二)—— SqlAlchemy

    SqlAlchemy SQLAlchemy是Python编程语言下的一款开源软件.提供了SQL工具包及对象关系映射(ORM)工具,使用MIT许可证发行. SQLAlchemy"采用简单的Py ...

  9. OpenCV开发笔记(八十):基于特征点匹配实现全景图片拼接

    前言   一个摄像头视野不大的时候,我们希望进行两个视野合并,这样让正视的视野增大,从而可以看到更广阔的标准视野.拼接的方法分为两条路,第一条路是Sticher类,第二条思路是特征点匹配.  本篇使用 ...

  10. CMake构建学习笔记14-依赖库管理工具

    如果说做C/C++开发最大的痛点是什么,那么一定是缺少一个官方的统一的包管理器.认真的说,如果你要用C/C++干点什么,至少需要(Windows系统下): C/C++语言本身.标准库.以及操作系统AP ...