Django源码解析:middleware

来源:互联网 发布:清华大学网络 编辑:程序博客网 时间:2024/05/19 19:57
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

 

0 0
原创粉丝点击