zoukankan      html  css  js  c++  java
  • Django源码解析:middleware

    1. middleware简介

    Django的middleware的概念相当于SSH框架里面的filter的概念。中间键的作用就是对所有的request,在request前,和在response后做一定的处理。

    Django的中间键类型分为五种:

    • 请求(Request)中间件->对应函数process_request
    • 视图(View)中间件->对应函数process_view
    • 模板(Template)中间件->对应函数process_template_response
    • 响应(Response)中间件->对应函数process_response
    • 异常(Exception)中间件->对应函数process_exception

    我们在自定义中间键的时候,至少需要实现上面的五个函数之一。

    2. middleware中间键函数的执行顺序和过程


    (1)总述

    1. 应用请求中间件,处理传入请求.如果请求中间件方法process_request返回的response非空,则终止处理过程,执行步骤7.

    2. url匹配,查找视图函数

    3. 应用视图中间件,处理传入请求 视图与视图参数.如果视图中间件方法process_view返回的response非空,则终止处理过程,执行步骤7.

    4. 调用视图函数.

    5. 如果视图函数抛出异常 ,应用异常中间件,处理传入请求与异常.如果异常中间件方法process_exception回的response非空,则终止处理过程.无论是否终止过程,都会跳到步骤7.

    6. 如果response支持延迟渲染,应用模板中间件.(If the response supports deferred rendering, apply template response middleware and the render the response).执行步骤7.

    7. 应用响应中间件,处理传入请求与中间件返回的response.


    (2)当Handler接受到客户端的请求过程的处理细节过程

    具体的处理函数的文件定义在django/core/handler/base.py文件之中

    当handler接受到一个客户端的请求的时候,其执行过程如下

    1. 根据setting.py配置的MIDDLEWARE_CLASSES,import相应的包。然后很据里面定义的5中类型的中间键,提取出来,保存在self._request_middleware,self._view_middleware ,self._template_response_middleware ,self._response_middleware ,self._exception_middleware这五个list变量中。

    self._view_middleware = []
            self._template_response_middleware = []
            self._response_middleware = []
            self._exception_middleware = []
    
            request_middleware = []
            for middleware_path in settings.MIDDLEWARE_CLASSES:
                mw_class = import_string(middleware_path)
                try:
                    # 实例化该middleware 如果不存在该类文件,则跳过
                    mw_instance = mw_class()
                except MiddlewareNotUsed:
                    continue
    
                if hasattr(mw_instance, 'process_request'):
                    request_middleware.append(mw_instance.process_request)
                if hasattr(mw_instance, 'process_view'):
                    self._view_middleware.append(mw_instance.process_view)
    
                # 倒序的插入的,因此从reponse后的middleware的函数,是从后往前执行的
                if hasattr(mw_instance, 'process_template_response'):
                    self._template_response_middleware.insert(0, mw_instance.process_template_response)
                if hasattr(mw_instance, 'process_response'):
                    self._response_middleware.insert(0, mw_instance.process_response)
                if hasattr(mw_instance, 'process_exception'):
                    self._exception_middleware.insert(0, mw_instance.process_exception)
    

    从上面的代码我们也可以看出:对于配置的middleware中间键,其执行过程是有顺序的。在request传入的过程中,process_request和process_view函数,是按照配置的顺序从上往下执行的。在response函数返回的过程中,其执行顺序是,按照配置的中间键顺序从下往上执行的。

    image

    2.执行request的middleware

    从代码中,我们可以看出,当middleware函数返回非None的时候,就直接跳转到response的middleware的阶段了,不再去继续执行下面的request的middleware函数。

     # Apply request middleware
                # 遍历前面保存的middleware里面的request方法,并且进行执行
                for middleware_method in self._request_middleware:
    
                    # request方法是没有返回值的,如果有返回那么就退出了
                    response = middleware_method(request)
                    if response:
                        break
    

    3.根据请求的路径,查找相应的处理的view

    if response is None:
                    # 根据reques.path_info和配置的urlconf的urls进行匹配,查找相应的处理的view
                    if hasattr(request, 'urlconf'):
                        # Reset url resolver with a custom urlconf.
    
                        # 该request可能有自己的urlconf
                        urlconf = request.urlconf
                        urlresolvers.set_urlconf(urlconf)
                        resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
    
                    resolver_match = resolver.resolve(request.path_info)
                    callback, callback_args, callback_kwargs = resolver_match
                    request.resolver_match = resolver_match

    4. 执行view的middleware

      # Apply view middleware
                    # 执行view的middlerware
                    for middleware_method in self._view_middleware:
                        response = middleware_method(request, callback, callback_args, callback_kwargs)
                        if response:
                            break

    5.执行view函数,得到response。如果有异常,就执行exception的middleware

    if response is None:
                    # 执行view函数
    
                    wrapped_callback = self.make_view_atomic(callback)
                    try:
                        response = wrapped_callback(request, *callback_args, **callback_kwargs)
    
                    # 如果出现异常,那么就执行异常的middleware
                    except Exception as e:
                        # If the view raised an exception, run it through exception
                        # middleware, and if the exception middleware returns a
                        # response, use that. Otherwise, reraise the exception.
                        for middleware_method in self._exception_middleware:
                            response = middleware_method(request, e)
                            if response:
                                break
                        if response is None:
                            raise

    6. 执行response的middleware,得到最终的返回给客户端的response

     # If the response supports deferred rendering, apply template
                # response middleware and then render the response
                # 如果是render类型的response,就去执行render的middleware
                if hasattr(response, 'render') and callable(response.render):
                    for middleware_method in self._template_response_middleware:
                        response = middleware_method(request, response)
                    response = response.render()

    3. 参考文章

    1. Django源码解析(四) 中间件

    2. https://docs.djangoproject.com/en/1.8/topics/http/middleware/#process_view

  • 相关阅读:
    Tomcat卸载重装后重装后出现的无法启动的问题
    主页面刷新 illegalStateException:stream
    JVM内存管理机制
    Java代码操作SVN
    FilenameFilter总结
    Java四种引用解析以及在Android的应用
    关于java中MD5加密(可直接使用)
    学习Java有没有什么捷径?
    深入分析java传参
    Java发展前景与职业方向解析
  • 原文地址:https://www.cnblogs.com/weishenhong/p/4929800.html
Copyright © 2011-2022 走看看