Django源码解读之MIddleware(中间件)

Django中间件的原理

一般中间件都是通过闭包来实现,django是通过装饰器(也是闭包的一个类型)实现。本质类似是入栈操作FILO

  • 首先功过WSGIHandler的实例调用self.load_middleware(),加载父类的Basehandler.load_middleware()方法
  class WSGIHandler(base.BaseHandler):
      request_class = WSGIRequest
  
      def __init__(self, *args, **kwargs):
          super().__init__(*args, **kwargs)
          self.load_middleware()
  • 套娃的思想是传入callable通过装饰器返回的是嵌套的callable

  • 重点是看如何实现套娃的,下面的mw_instance是中间件实例,也就是callable

    class BaseHandler:
    
        def load_middleware(self):
            handler = self.get_response
            for middleware in reversed(MIDDLEWARE):
                mw_instance = middleware(handler) # handler是函数callable,mw_instance有__call__也是callable
                handler = convert_exception_to_response(mw_instance)
            self._middleware_chain = handler
    
        def get_response(self, request):
            print("get response %s" % request)
            
    def convert_exception_to_response(get_response):
        @wraps(get_response)
        def inner(request):
            try:
                response = get_response(request)
            except Exception as exc:
                response = "exc %s" % exc
            return response
    
        return inner
    

完整查看示例

from functools import wraps

def convert_exception_to_response(get_response):
    @wraps(get_response)
    def inner(request):
        try:
            response = get_response(request)
        except Exception as exc:
            response = "exc %s" % exc
        return response

    return inner

class Middleware1:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        print(self.__class__.__name__, request)
        self.get_response(request)


class Middleware2:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        print(self.__class__.__name__, request)
        self.get_response(request)


class Middleware3:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        print(self.__class__.__name__, request)
        self.get_response(request)


MIDDLEWARE = [Middleware1, Middleware2, Middleware3]


class BaseHandler:

    def load_middleware(self):
        handler = self.get_response
        for middleware in reversed(MIDDLEWARE):
            mw_instance = middleware(handler)
            handler = convert_exception_to_response(mw_instance)
        self._middleware_chain = handler

    def get_response(self, request):
        print("get response %s" % request)


if __name__ == '__main__':
    b = BaseHandler()
    b.load_middleware()
    request = "request"
    b._middleware_chain(request)
# 执行_middleware_chain(request) 输出
#Middleware1 request
#Middleware2 request
#Middleware3 request
#get response request
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容