Django一分钟:深入讲解中间件,学会自定义中间件

加载中间件

django服务器在启动和初始化过程中会对settings.py配置文件中的MIDDLEWARE列表中配置的中间件进行加载:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

加载中间件的工作具体由BaseHandler.laod_midddleware方法实现:

class BaseHandler:
    _view_middleware = None
    _template_response_middleware = None
    _exception_middleware = None
    _middleware_chain = None

    def load_middleware(self, is_async=False):
        """
        Populate middleware lists from settings.MIDDLEWARE.
        ...

这是服务器启动过程中做的工作,此时还不涉及任何请求的接收和处理。

请求处理

  1. 请求进来之后,Django将创建线程进行处理,具体构建socket的过程不在此处讨论,总之会把请求封装为HttpRequest,此对象包含了一个请求的基本信息,实际处理的时候可能是它的基类WSGIRequest(HttpRequest),但这不重要。
class HttpRequest:
    """A basic HTTP request."""
    ...
    def __init__(self):
        ...
        self.GET = QueryDict(mutable=True)
        self.POST = QueryDict(mutable=True)
        self.COOKIES = {}
        self.META = {}
        self.FILES = MultiValueDict()

        self.path = ""
        self.path_info = ""
        self.method = None
        self.resolver_match = None
        self.content_type = None
        self.content_params = None
        ...
  1. 接下来Django要对请求做下一步的处理,用于处理请求的工具就是上面提到的BaseHandler,具体来说可能是它的子类WSGIHandler(base.BaseHandler),但这不重要。
  2. 我们再初始化时就将所有中间件导入进BaseHandler中,它将用这些中间件对请求进行处理(想象一条流水线):
class BaseHandler:
    ...
    def get_response(self, request):
        ...
        response = self._middleware_chain(request)
        ...

深入中间件

我们现在知道,中间件在Django启动时被加载,当一个请求进来的时候中间件会按顺序(想象一条流水线)对请求进行处理,现在我们进入单个中间件中,看看究竟发生了什么。

MiddlewareMixin是所有中间件的基类,当它被调用的时候,它会去寻找自身的process_request方法,由process_request方法对请求对象进行处理。

class MiddlewareMixin:
    ...
    # 此处可以看到中间件在处理请求,具体来说调用了自己的process_request方法
    def __call__(self, request):
        ...
        if hasattr(self, "process_request"):
            response = self.process_request(request)
        ...

因此自定义中间件的关键就在于继承MiddlewareMixin,并重写process_request方法。以Django自带的SessionMiddleware为例,它的实现非常简单,就是重写了process_request方法,实现了取出请求对象中的cookie信息并存储起来的逻辑:

class SessionMiddleware(MiddlewareMixin):
    def __init__(self, get_response):
        super().__init__(get_response)
        engine = import_module(settings.SESSION_ENGINE)
        self.SessionStore = engine.SessionStore
    
     
    def process_request(self, request):
        # 取出请求对象并存储    
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
        request.session = self.SessionStore(session_key)
        ...

中间件还能对视图函数处理完返回的响应对象再做处理,对应的只需要重写process_response方法,不细致讨论,都是一样的道理,讲这么多就足够了。

总结

因此总结,自定义中间件只需三步:

  1. 创建自己的中间件类继承SessionMiddleware
  2. 想处理请求就重写process_request,想处理响应就重写process_response
  3. 最后需要的中间件注册到MIDDLEWARE列表中,注意顺序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值