django中间件实现原理

django中间件实现原理:递归回调
图一
图二

    def load_middleware(self):
        """
        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 = []

        handler = convert_exception_to_response(self._get_response)             handle1  #不同于其他handle,相当一个出口,在图二中相当于中心,执行view视图逻辑
        for middleware_path in reversed(settings.MIDDLEWARE): 
            middleware = import_string(middleware_path)
            try:
				
				#初始化每个middleware并且,把handle传入
				这个handler是上一个的middleware实体
                mw_instance = middleware(handler)                               
				
				#hander每次不一样
				handler = convert_exception_to_response(mw_instance)            handle[i]
           		
           ... ...
           
        self._middleware_chain = handler                                         handle2  #相当于一个进口,进入中间件中
1、在上述例程中,开始遍历所有中间件之前,handler1赋值给调用实体的_get_response成员函数,而_get_response()中包含了view函数的调用。

handler = convert_exception_to_response(self._get_response)

2、遍历所有中间件过程中,加载并初始化(middleware()调用对应着__init__成员函数)中间件,因此中间件的get_response赋值为handler[i],注意middleware()返回一个中间件类实体

mw_instance = middleware(handler)。#实体

3、接着调用调用handler = convert_exception_to_response (mw_instance),convert_exception_to_response只是对输入函数进行了容错封装,在分析逻辑时,可以简单看成输入函数本身,因此,相当于handler = mw_instance(request),对于一个类实体调用即调用__call__成员函数,但返回的还是实体mw_instance。

handler = convert_exception_to_response (mw_instance) #mw_instance(request) #调用实体的call方法
convert_exception_to_response是一个装饰器:

def convert_exception_to_response(get_response):
    """
    Wrap the given get_response callable in exception-to-response conversion.

    All exceptions will be converted. All known 4xx exceptions (Http404,
    PermissionDenied, MultiPartParserError, SuspiciousOperation) will be
    converted to the appropriate response, and all other exceptions will be
    converted to 500 responses.

    This decorator is automatically applied to all middleware to ensure that
    no middleware leaks an exception and that the next middleware in the stack
    can rely on getting a response instead of an exception.
    """
    @wraps(get_response)
    def inner(request):
        try:
            response = get_response(request)
        except Exception as exc:
            response = response_for_exception(request, exc)
        return response
    return inner

(1)、handler = convert_exception_to_response (mw_instance) = mw_instance = self.get_response
(2)、self._middleware_chain(request) = handle(request) = response = get_response(request)= mw_instance(request)=self.get_response(request)

4、从目前来看,大部分的中间件并没有重写该成员函数,因此是直接调用基类的成员函数,即: MiddlewareMixin. call(self)。因此handler[i] = MiddlewareMixin. call(self)。
class MiddlewareMixin:
    def __init__(self, get_response=None):
        self.get_response = get_response
        super().__init__()

    def __call__(self, 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
5、注意该函数有一个self输入参数,各个中间件在调用时,传入该中间件对应的self实体,这样self.process_request, self.process_response的调用就分别对应着不同方法的处理函数。load_middleware()调用之后,各个中间件初始化完成并通过get_response链接起来,这样一个request请求到来时,可以顺序通过各个中间件依次进行处理。
6、在调用的最后,将self._middleware_chain = handler2,类似于将中间件链表的链表头保存起来,下次处理时,从该链表头开始进行遍历处理。
MiddlewareMixin基类其中有三个重要的结构构成:process_request()、get_response()、process_response(),而get_response()通常指向下一个中间件的__call__成员函数(中间件链表的最后一个中间件除外,其get_response()指向handler1,进行view逻辑处理),由于各个中间件的get_response()这一特性(绝大部分指向基类__call__成员函数),使得中间件链表处理有点类似递归调用的感觉。这一递归调用顺序,决定了各个中间件处理的一些特点:

1、最先进行流程处理的中间件,其process_request()(如果存在的话)最先被执行,但是其process_response()(如果存在的话)却最后得到处理,因为只有执行完后面的get_response()前面的才能接着执行。

2、最后进行流程处理的中间件,其process_request()(如果存在的话)最后被执行,但是其process_response()(如果存在的话)紧接着得到处理。

3、在中间件处理流程中,如果出现某个中间件的process_request()返回了response,这种情况通常是处理过程中出现了异常情况,该中间件后续的中间件不再参与处理,直接调用该中间件的process_response()(如果存在的话),或者直接返回。

注:但是需要注意的是MiddlewareMixin这个基类,可能以后就会被放弃使用,因此可以直接不用继承,直接把方法写在自定义中间件中,以后防止修改。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值