首页 > 其他分享 >关于django中间件执行过程

关于django中间件执行过程

时间:2023-10-15 22:44:37浏览次数:51  
标签:get process middleware 中间件 django self handler 执行 response

众所周知,django的中间件一般有五个方法,常用的仅三个,示例如下

from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse
中间件示例
class MyMiddleWare(MiddlewareMixin): 
	def process_request(self,request):
		pass
	def process_view(self,request):
		pass
	def process_response(view,request,response):
		pass
		# 少用,视图函数报错,会走这个方法
	def process_exception(self,request,excetion):
		print(excetion)
        return HttpResponse("服务器异常了")
		# 依旧少用
	def process_template_response(self,*args,**kwargs):
		pass

关于django请求的入口

本质上就是一个WSGIHandler() 对象

def get_wsgi_application():
    django.setup(set_prefix=False)
    return WSGIHandler()

django启动的时候对WSGIHandler 对象进行了实例化,会执行其构造方法, 而当用户请求到来的时候,会 引用这个对象() 会执行对应的__call__方法

class WSGIHandler(base.BaseHandler):
    request_class = WSGIRequest

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.load_middleware()

    def __call__(self, environ, start_response):
        ......

关于中间件的初始化加载:

关于wsgihandler对象的构造方法,它其实就两步,第一步掉用父类构造方法,第二步,执行self.load_middleware()方法,顾名思义,这个方法就是处理加载中间件的逻辑.

load_middleware() 加载逻辑之源码

def load_middleware(self, is_async=False):
	self._view_middleware = []
	self._template_response_middleware = []
	self._exception_middleware = []
# 这里是准备三个容器,来存放所有中间件的 process_view,process_template_response,process_exception三个方法。

#  三元表达式,如果是同步请求,则get_response  应该为 self._get_response
#  convert_exception_to_response 实际上就是在里面做了个闭包,把执行self._get_response方法进行了打包取名为inner函数返回给handler,后续如果希望执行self._get_response() 方法,直接handler()即可
	get_response = self._get_response_async if is_async else self._get_response
	handler = convert_exception_to_response(get_response)
	
	handler_is_async = is_async  # 这一步是处理异步逻辑的,暂且忽略

# 通过 reversed进行逆序 遍历配置文件中注册的所有中间件,并且通过import_string实现动态导入,然后通过反射,获取模块中的类。 本质上import_string内做了import_module方法导入和getattr反射。
	for middleware_path in reversed(settings.MIDDLEWARE):
		middleware = import_string(middleware_path)  # 所以此时,middleware表示遍历到的每一个
		......(此处省略对异步请求的逻辑处理)
		
		#  adapt_method_mode 方法接收了handler,对其进行了打包,最后还是把handler返回给了adapted_handler,所以此时可以把adapted_handler 直接理解为之前那个可以间接调用_get_response方法的handlerl。
		# mw_instance = middleware(adapted_handler)  因为middleware 是我们的中间件类,这里对其进行实例化,并且把adapted_handler也就是handler传递给其构造方法。最终应该是执行这些中间件类继承的MiddlewareMixin的构造方法。其构造方法,接收get_response形参也就是adapter_handler其实也就是handler 所以,后续如果mw_instance.get_response 其实就是在执行self._get_response()
		try:
			# 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:
			......
			
		......
		

------------


		
这里三个反射,很明显,分别通过反射机制,从mw_instance这一中间件实例对象身上获取对应的
process_view,process_template_response,process_exception三方法,
将其放入之前准备好的三个容器中,值得注意的是,for遍历的时候进行了逆序,然后这里的process_view
是每次遍历到一个插入到第一个 ,另外两个是放到最后,所以最终结果应该是只有process_view
和配置文件中的顺序一致,另外俩是相反的
```python
		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"):
			self._exception_middleware.append(
				self.adapt_method_mode(False, mw_instance.process_exception),
			)
	# convert_exception_to_response 刚说过,他本质上就是在做一个闭包,也就是通过调用handler可以间接的调用mw_instance ,而mw_instance 其实是handler 所以这里的handler还是handler
		handler = convert_exception_to_response(mw_instance)
		handler_is_async = middleware_is_async
			
			

至此,准备结束,此时,如果请求到来,会执行mw_instance(),而 mw_instance是中间件类的示例,所以它会执行中间件类中的__call__ 方法,分析如下图
image

#  此处的handler相当于具有三个功能 (执行process_request(),self._get_response(包括路由匹配和执行视图函数),执行process_response()) 
		handler = convert_exception_to_response(mw_instance)
		handler_is_async = middleware_is_async
			



至此第一个中间件准备ok
假设我们有ABCD 四个中间件,此时,A中间件加载完毕,假设 handler是这样的
[(A)process_request(),(A)get_response,(A)process_response()]

此时开始加载第二个中间件视线回到for循环
for middleware_path in reversed(settings.MIDDLEWARE):
		middleware = import_string(middleware_path)  # 所以此时,middleware表示遍历到的每一个
	try:
			# 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:
值得注意的是,此处的handler,是第一个中间件的最后的handler
此时  adapted_handler = hander = [(A)process_request(),(A)get_response,(A)process_response()]
mw_instance = B( [(A)process_request(),(A)get_response,(A)process_response()]) 
mw_instance.get_response =  [(A)process_request(),(A)get_response,(A)process_response()]
mw_instance()  ==> [(B)process_request(),[(A)process_request(),(A)get_response,(A)process_response()],(B)process_response()]
逐层嵌套的图示

handler = D对象
		D对象()  触发call方法
		(D)process_request()
		get_response = C对象
		(D)process_response()
				执行call方法
				(C)process_request()
				get_response = B对象
				(C)process_response()
						执行call方法
						(B)process_request()
						get_response = A对象
						(B)process_response()
									执行call方法
									(A)process_request()
									get_response = self.get_resposne()  # 路由匹配,执行视图函数
									(A)process_response()



标签:get,process,middleware,中间件,django,self,handler,执行,response
From: https://www.cnblogs.com/yu-xin666/p/17766370.html

相关文章

  • 车辆车型识别系统python+TensorFlow+Django网页界面+算法模型
    一、介绍车辆车型识别系统。本系统使用Python作为主要开发编程语言,通过TensorFlow搭建算法模型网络对收集到的多种车辆车型图片数据集进行训练,最后得到一个识别精度较高的模型文件。并基于该模型搭建Django框架的WEB网页端可视化操作界面。实现用户上传一张车辆车型图片识别其名称......
  • django 静态文件
     静态: STATIC_URL='static/'STATIC_ROOT=os.path.join(BASE_DIR,'/static/')STATICFILES_DIRS=(os.path.join(BASE_DIR,'static'),)STATIC_ROOT=os.path.join(BASE_DIR,'static/')===错误pythonmanage.pycolle......
  • 车辆车型识别系统python+TensorFlow+Django网页界面+算法模型
    一、介绍车辆车型识别系统。本系统使用Python作为主要开发编程语言,通过TensorFlow搭建算法模型网络对收集到的多种车辆车型图片数据集进行训练,最后得到一个识别精度较高的模型文件。并基于该模型搭建Django框架的WEB网页端可视化操作界面。实现用户上传一张车辆车型图片识别其名......
  • Django开发要点
    一、内置标签及自定义标签描述"{%for%}"遍历输出上下文的内容"{%if%}"对上下文进行条件判断"{%csrf_token%}"生成csrf_token的标签,用于防护跨站请求伪造攻击"{%url%}"引用路由配置的地址,生成相应的路由地址"{%with%}"将上下文重新命名"{%......
  • 程序并发执行和前驱图
         ......
  • 使用Pycharm环境,搭建Django开发环境
    早期都会直接在Linux系统下,直接把很多py包装到物理系统里。不过事实证明,装在虚拟环境里要方便得多,尤其是早期很多工程做到一半发现写不下去了。假如IDE选择的是Pycharm的话,实际上在它的工具里,就非常方便了。 新建一个工程后,在Pycharm里,点击如上图所示的蓝色按钮,就进入了虚拟......
  • Django 代码部署运行(Windows)
     安装git 准备好文件夹E:\_prjct\boshi_xinxi_caiji\codes2 启动gitbash$pwd/E/_prjct/boshi_xinxi_caiji/codes2$gitclonehttps://gitee.com/xautstar/doctoral-dissertation-collection.git   创建数据库collection,修改用户和密码  在sqlyog......
  • Django Nginx+uwsgi 安装配置
    DjangoNginx+uwsgi安装配置在前面的章节中我们使用pythonmanage.pyrunserver来运行服务器。这只适用测试环境中使用。正式发布的服务,我们需要一个可以稳定而持续的服务器,比如apache,Nginx,lighttpd等,本文将以Nginx为例。你也可以直接参考:Pythonuwsgi安装配置安......
  • strapi系列-常用操作记录(创建中间件,创建关系型数据库,数据去掉attributes那一层)
    创建全局中间件创建关系型的数据https://docs.strapi.io/dev-docs/api/rest/relations{"product_types":{"connect":[10]},"product_tags":{"connect":[7,3,4]},"name":"TEST","......
  • Mysql SELECT 语句执行过程
    整个SELECT语句查询流程1、客户端/服务端通信协议(Connectors)Mysql客户端/服务端通讯协议是半双工的,这就意味着在任意时刻只能有一端能发送数据,要么是客户端向服务端发送数据,要么是服务端向客户端发送数据,这两个动作不能同时进行,一旦一端开始发送数据,另外一端要完整......