Django中间件的源码解析流程(上)——中间件载入的前置

目录

1. ​前言​

2. 请求的入口

3. 中间件加载的入口

4. 源码中的闭包实现

5. 最后


1. 前言

哈喽,大家好,我是小K,今天咋们分享的内容是:在学会Django中间件之后, 我们继续深入底层源码。

在执行中间件时请求到来总是从前往后逐一匹配,但当响应返回时,执行的中间件顺序往往是反着执行的。

在Django中间件中,采用了多层闭包的形式,以来达到逐一执行中间件,本篇文章主要是从请求的入口开始,简单介绍一下前置。

如果还不会使用中间件的小伙伴可以跳转到这里:

Django之五种中间件定义类型

2. 请求的入口

在同步请求中,请求的入口其实就是 wsgi.py 文件, 不清楚的可以跳转这里,看第2点:

Django源码之路由匹配(下)——图解逐步分析底层源码

3. 中间件加载的入口

在请求到来时,最后返回的是一个WSGIHandler的一个对象

application = get_wsgi_application()def get_wsgi_application():django.setup(set_prefix=False)return WSGIHandler()class WSGIHandler(base.BaseHandler):request_class = WSGIRequestdef __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)self.load_middleware()

在加载对象时,肯定是少不了执行__init__的初始化方法的

self.load_middleware()   # 这其实就是加载中间件的方法

在执行load_middleware()函数时,首先是在自己的类中寻找,如果没有就去父类中寻找

显然,这里的代码是需要我们去父类BaseHandler类中寻找的


这里BaseHandler类和load_middleware的源码:

class BaseHandler:_view_middleware = None_template_response_middleware = None_exception_middleware = None_middleware_chain = Nonedef load_middleware(self, is_async=False):"""Populate middleware lists from settings.MIDDLEWARE.Must be called after the environment is fixed (see __call__ in subclasses)."""self._view_middleware = []self._template_response_middleware = []self._exception_middleware = []get_response = self._get_response_async if is_async else self._get_responsehandler = convert_exception_to_response(get_response)handler_is_async = is_asyncfor middleware_path in reversed(settings.MIDDLEWARE):middleware = import_string(middleware_path)middleware_can_sync = getattr(middleware, "sync_capable", True)middleware_can_async = getattr(middleware, "async_capable", False)if not middleware_can_sync and not middleware_can_async:raise RuntimeError("Middleware %s must have at least one of ""sync_capable/async_capable set to True." % middleware_path)elif not handler_is_async and middleware_can_sync:middleware_is_async = Falseelse:middleware_is_async = middleware_can_asynctry:# Adapt handler, if needed.adapted_handler = self.adapt_method_mode(middleware_is_async,handler,handler_is_async,debug=settings.DEBUG,name="middleware %s" % middleware_path,)mw_instance = middleware(adapted_handler)except MiddlewareNotUsed as exc:if settings.DEBUG:if str(exc):logger.debug("MiddlewareNotUsed(%r): %s", middleware_path, exc)else:logger.debug("MiddlewareNotUsed: %r", middleware_path)continueelse:handler = adapted_handlerif mw_instance is None:raise ImproperlyConfigured("Middleware factory %s returned None." % middleware_path)if hasattr(mw_instance, "process_view"):self._view_middleware.insert(0,self.adapt_method_mode(is_async, mw_instance.process_view),)if hasattr(mw_instance, "process_template_response"):self._template_response_middleware.append(self.adapt_method_mode(is_async, mw_instance.process_template_response),)if hasattr(mw_instance, "process_exception"):# The exception-handling stack is still always synchronous for# now, so adapt that way.self._exception_middleware.append(self.adapt_method_mode(False, mw_instance.process_exception),)handler = convert_exception_to_response(mw_instance)handler_is_async = middleware_is_async# Adapt the top of the stack, if needed.handler = self.adapt_method_mode(is_async, handler, handler_is_async)# We only assign to this when initialization is complete as it is used# as a flag for initialization being complete.self._middleware_chain = handler

 ok,我们现在着重来分析load_middleware的源码

4. 源码中的闭包实现

先来看看什么是闭包:

Python奇幻之旅(从入门到入狱基础篇)——附相关资料【中】-CSDN博客

这篇文章里面有一部分介绍了闭包和装饰器

现在来看具体的闭包实现函数:

def convert_exception_to_response(get_response):if iscoroutinefunction(get_response):@wraps(get_response)async def inner(request):try:response = await get_response(request)except Exception as exc:response = await sync_to_async(response_for_exception, thread_sensitive=False)(request, exc)return responsereturn innerelse:@wraps(get_response)def inner(request):try:response = get_response(request)except Exception as exc:response = response_for_exception(request, exc)return responsereturn inner

最后返回了一个inner函数, 而这个inner调用的是get_response()

最后都被封装进了handler里面

5. 最后

本文只是简单介绍了一下中间件加载的位置,下一篇文章将采用长篇的形式详细讲解中间件是如何通过闭包的形式载入的。今天就先到这里啦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/637679.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云原生Kubernetes: K8S 1.29版本 部署ingress-nginx

目录 一、实验 1.环境 2. K8S 1.29版本 部署ingress-nginx 二、问题 1.kubectl 如何强制删除 Pod、Namespace 资源 2.创建pod失败 3.pod报错ImagePullBackOff 4.docker如何将镜像上传到官方仓库 5.创建ingress报错 一、实验 1.环境 (1)主机 表…

The C programming language (second edition,KR) exercise(CHAPTER 4)

E x c e r c i s e 4 − 1 Excercise\quad 4-1 Excercise4−1&#xff1a; #include <stdlib.h> #include <stdio.h> #include <string.h> int strindex(char s[],char t[]); int strrindex(char s[],char t[]);int main(void) {char s[100]"qwoulddf…

m个人的成绩存放在score数组中,请编写函数fun,它的功能是:将低于平均分的人数作为函数值返回,将低于平均分的分数放在below所指的数组中。

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法和详细的解析。 题干 m个人的成绩…

linux的编译器vim

vim简介 之前我们在win下写代码&#xff0c;都是下载一些编译器VS/eclipse等 他们不仅可以写代码&#xff0c;还可以实现代码的运行调试&#xff0c;开发。这样的编译器叫做集成编译器 而linux中虽然也有这样的编译器&#xff0c;但不管是从下载&#xff0c;还是使用中都会显…

同旺科技 USB TO SPI / I2C适配器读写24LC128--读写

所需设备&#xff1a; 1、USB 转 SPI I2C 适配器&#xff1b;内附链接 2、24LC128芯片&#xff1b; 适应于同旺科技 USB TO SPI / I2C适配器专业版&#xff1b; 专业版配套软件更新&#xff1b; 直接读取HEX文件&#xff0c;自动完成文件解析&#xff1b; 支持芯片&#xf…

C++的初步知识——命名空间,缺省参数,重载函数

C 首先写一段代码&#xff1a; #include <stdio.h>int main() {printf("Hello world\n");return 0; }这段C语言代码在cpp文件中仍可运行。我们了解C是兼容C语言的&#xff0c;C的关键字中就包含了C语言的关键字和自身的关键字。关于关键字&#xff0c;我们简…

Elasticsearch进阶篇(三):ik分词器的使用与项目应用

ik分词器的使用 一、下载并安装1.1 已有作者编译后的包文件1.2 只有源代码的版本1.3 安装ik分词插件 二、ik分词器的模式2.1 ik_smart演示2.2 ik_max_word演示2.3 standard演示 三、ik分词器在项目中的使用四、ik配置文件4.1 配置文件的说明4.2 自定义词库 五、参考链接 一、下…

C++ | Leetcode C++题解之第42题接雨水

题目&#xff1a; 题解&#xff1a; class Solution { public:int trap(vector<int>& height) {int n height.size();if (n 0) {return 0;}vector<int> leftMax(n);leftMax[0] height[0];for (int i 1; i < n; i) {leftMax[i] max(leftMax[i - 1], he…

8.idea中一个服务启动多实例

指定一个新的端口-Dserver.port8082

T1级,生产环境事故—Shell脚本一键备份K8s的YAML文件

大家好&#xff0c;我叫秋意零。 最近对公司进行日常运维工作时&#xff0c;出现了一个 T1 级别事故。导致公司的“酒云网”APP的无法使用。我和我领导一起搞了一个多小时&#xff0c;业务也停了一个多小时。 起因是&#xff1a;我的部门直系领导&#xff0c;叫我**删除一个 …

软件杯 深度学习实现行人重识别 - python opencv yolo Reid

文章目录 0 前言1 课题背景2 效果展示3 行人检测4 行人重识别5 其他工具6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的行人重识别算法研究与实现 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c…

MultiHeadAttention在Tensorflow中的实现原理

前言 通过这篇文章&#xff0c;你可以学习到Tensorflow实现MultiHeadAttention的底层原理。 一、MultiHeadAttention的本质内涵 1.Self_Atention机制 MultiHeadAttention是Self_Atention的多头堆嵌&#xff0c;有必要对Self_Atention机制进行一次深入浅出的理解&#xff0c;这…