众所周知,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__ 方法,分析如下图
# 此处的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