作为一个工作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. springboot整合validation统一参数检查

    1.背景 实际开发中对参数进行检查,是常见 比如如下代码 /** * 参数检查测试(传统做法) * * @param dto * @return */ @GetMapping("/param ...

  2. 08-canvas绘制表格

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  3. SMU Summer 2024 Contest Round 3

    SMU Summer 2024 Contest Round 3 寻找素数对 题意 给你一个偶数,找到两个最接近的素数,其和等于该偶数. 思路 处理出 1e5 以内的素数,然后遍历,更新最接近的答案. ...

  4. Blazor开发框架Known-V2.0.9

    V2.0.9 Known是基于Blazor的企业级快速开发框架,低代码,跨平台,开箱即用,一处代码,多处运行.本次版本主要是修复一些BUG和表格页面功能增强. 官网:http://known.puma ...

  5. 使用 updateAppConfig 更新 Nuxt 应用配置

    title: 使用 updateAppConfig 更新 Nuxt 应用配置 date: 2024/8/27 updated: 2024/8/27 author: cmdragon excerpt: ...

  6. 【解决方案】项目重构之如何使用 MySQL 替换原来的 MongoDB

    目录 前言 一.痛点所在 二.选型分析 2.1特点对比 2.2场景对比 三.核心思路 四.demo 示例 4.1实体映射 4.1.1MongoDB 实体 4.1.2MySQL 实体 4.2查询代码 4 ...

  7. Go plan9 汇编:内存对齐和递归

    Go plan9 汇编系列文章: Go plan9 汇编: 打通应用到底层的任督二脉 Go plan9 汇编:手写汇编 Go plan9 汇编:说透函数栈 0. 前言 在 Go plan9 汇编系列文 ...

  8. TypeScript – 冷知识

    当 generic return 遇上 parameter 报错了.原因是 querySelector 默认返回类型是抽象的 Element. 而 method 参数要求的是具体的 InputElem ...

  9. JavaScript – 理解 Function, Object, Prototype, This, Class, Mixins

    前言 JavaScript (简称 JS) 有几个概念 Object, Prototype, This, Function, Class 是比较难理解的 (相对其它语言 C# / Java 而已),这 ...

  10. HTML & CSS – 实战 RWD Image 响应式图片

    前言 之前写过 HTML & CSS – Responsive Image 响应式图片 (完整版), 里面解释了原理和一些具体做法, 但是并不是以真实场景作为例子带入. 由于 RWD Imag ...