介绍

在django中,中间件其实就是一个类,在一个请求到来和这个请求结束之前,django会根据自己的规则在合适的时机执行中间件中相应的方法。

在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下: 



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',
]



使用

自定义中间件

创建中间件类



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from django.utils.deprecation import MiddlewareMixin
 2 
 3 
 4 class Middleware1(MiddlewareMixin):
 5     def process_request(self, request): print('from process_request')
 6 
 7     def process_view(self, request, callback, callback_args, callback_kwargs): print('from process_view')
 8 
 9     def process_template_response(self, request, response): print('from process_template_response')
10 
11     def process_exception(self, request, exception): print('from process_exception')
12 
13     def process_response(self, request, response):
14         print('from process_response')
15         return response
  • 中间件类
注册中间件



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 MIDDLEWARE = [
 2     'django.middleware.security.SecurityMiddleware',
 3     'django.contrib.sessions.middleware.SessionMiddleware',
 4     'django.middleware.common.CommonMiddleware',
 5     'django.middleware.csrf.CsrfViewMiddleware',
 6     'django.contrib.auth.middleware.AuthenticationMiddleware',
 7     'django.contrib.messages.middleware.MessageMiddleware',
 8     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 9     'Middleware.TestMiddleware.Middleware1'
10 ]
  • settings.py

中间件的钩子函数

中间件提供五个钩子函数供使用,分别是:

process_request

process_request(self,request)

  • request: process_request有一个参数,就是request,这个request和视图函数中的request是同一个对象。

我们来看看有多个中间件时,Django是如何执行其中的process_request方法:



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 MIDDLEWARE = [
 2     'django.middleware.security.SecurityMiddleware',
 3     'django.contrib.sessions.middleware.SessionMiddleware',
 4     'django.middleware.common.CommonMiddleware',
 5     'django.middleware.csrf.CsrfViewMiddleware',                            # 此项便是拦截CSRF请求的中间件
 6     'django.contrib.auth.middleware.AuthenticationMiddleware',
 7     'django.contrib.messages.middleware.MessageMiddleware',
 8     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 9     'Middleware.TestMiddleware.Middleware1'
10     'Middleware.TestMiddleware.Middleware2'
11 ]
  • settings.py



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from django.utils.deprecation import MiddlewareMixin
2 
3 
4 class Middleware1(MiddlewareMixin):
5     def process_request(self, request): print('from Middleware1.process_request')
6 
7 
8 class Middleware2(MiddlewareMixin):
9     def process_request(self, request): print('from Middleware2.process_request')
  • /Middleware/TestMiddleware.py



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from django.shortcuts import render,HttpResponse
2 
3 
4 def test(request):
5     print('from view func')
6     return HttpResponse('ok')
  • views.py



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from Middleware1.process_request
2 from Middleware2.process_request
3 from view func
  • 控制台输出: 1、中间件的process_request方法是在执行视图函数之前执行的。 2、当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的索引值,从前到后依次执行的。 3、不同中间件之间传递的request都是同一个对象。 4、它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而直接将该HttpResponse对象返回给浏览器。
process_response

process_response(self, request, response)

  • request: HttpRequest对象(请求对象)。 response: response是视图函数返回的HttpResponse对象。 给上述的Middleware1和Middleware2加上process_response方法:



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from django.utils.deprecation import MiddlewareMixin
 2 from django.shortcuts import HttpResponse
 3 
 4 
 5 class Middleware1(MiddlewareMixin):
 6     def process_request(self, request): print('from Middleware1.process_request')
 7 
 8     def process_response(self, request, response):
 9         print('from Middleware1.process_response')
10         return HttpResponse('ok')
11 
12 
13 class Middleware2(MiddlewareMixin):
14     def process_request(self, request): print('from Middleware2.process_request')
15 
16     def process_response(self, request, response):
17         print('from Middleware2.process_response')
18         return HttpResponse('ok')
  • /Middleware/TestMiddleware.py



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

from Middleware1.process_request
from Middleware2.process_request
from view func
from Middleware2.process_response
from Middleware1.process_response
  • 控制台输出: 1、process_response方法是在视图函数之后执行的。 2、多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的。 3、该方法的返回值必须是HttpResponse对象。
process_view

process_view(self, request, view_func, view_args, view_kwargs)

  • HttpRequest对象(请求对象)。 view_func: 请求所对应的视图函数句柄。 view_args: 传递给视图函数的位置参数。 view_kwargs: 传递给视图函数的关键字参数。

给上述的Middleware1和Middleware2加上process_view方法:



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from django.utils.deprecation import MiddlewareMixin
 2 from django.shortcuts import HttpResponse
 3 
 4 
 5 class Middleware1(MiddlewareMixin):
 6     def process_request(self, request): print('from Middleware1.process_request')
 7 
 8     def process_response(self, request, response):
 9         print('from Middleware1.process_response')
10         return HttpResponse('ok')
11 
12     def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware1.process_view')
13 
14 
15 class Middleware2(MiddlewareMixin):
16     def process_request(self, request): print('from Middleware2.process_request')
17 
18     def process_response(self, request, response):
19         print('from Middleware2.process_response')
20         return HttpResponse('ok')
21 
22     def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware2.process_view')
  • /Middleware/TestMiddleware.py



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from Middleware1.process_request
2 from Middleware2.process_request
3 from Middleware1.process_view
4 from Middleware2.process_view
5 from view func
6 from Middleware2.process_response
7 from Middleware1.process_response
  • 控制台输出: 1、process_view方法是在process_request之后,视图函数之前执行的。 2、它的执行顺序是按照MIDDLEWARE中的注册顺序从前到后顺序执行的。 3、它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续执行其他中间件的process_view方法,然后再执行相应的视图。 如果它返回一个HttpResponse对象,Django不会调用后续的视图函数。 而将直接执行中间件的process_response方法并将用该HttpResponse返回结果。
process_exception

process_exception(self, request, exception)

  • HttpRequest对象(请求对象)。 exception: exception是视图函数产生的Exception(异常)对象。

修改视图函数,并给上述的Middleware1和Middleware2加上process_exception方法:



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from django.shortcuts import render, HttpResponse
2 
3 
4 def test(request):
5     print('from view func')
6     i = 1 / 0
7     return HttpResponse('ok')
  • views.py



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from django.utils.deprecation import MiddlewareMixin
 2 from django.shortcuts import HttpResponse
 3 
 4 
 5 class Middleware1(MiddlewareMixin):
 6     def process_request(self, request): print('from Middleware1.process_request')
 7 
 8     def process_response(self, request, response):
 9         print('from Middleware1.process_response')
10         return HttpResponse('ok')
11 
12     def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware1.process_view')
13 
14     def process_exception(self, request, exception):
15         print('from Middleware1.process_exception')
16 
17 
18 class Middleware2(MiddlewareMixin):
19     def process_request(self, request): print('from Middleware2.process_request')
20 
21     def process_response(self, request, response):
22         print('from Middleware2.process_response')
23         return HttpResponse('ok')
24 
25     def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware2.process_view')
26 
27     def process_exception(self, request, exception):
28         print('from Middleware2.process_exception')
  • /Middleware/TestMiddleware.py



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

from Middleware1.process_request
from Middleware2.process_request
from Middleware1.process_view
from Middleware2.process_view
from view func
from Middleware2.process_exception
from Middleware1.process_exception
Internal Server Error: ...
ZeroDivisionError: division by zero
from Middleware2.process_response
from Middleware1.process_response
  • 控制台输出: 1、这个方法只有在视图函数中出现异常了才执行,并且是在process_response之前执行。 2、它的执行顺序是按照MIDDLEWARE中的注册顺序从前到后倒序执行的。 3、它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将在直接依次调用中间件中的process_response方法。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。
process_template_response

process_template_response(self, request, response)

  • HttpRequest对象(请求对象)。 response: response是视图函数返回的HttpResponse对象且这个对象中一定要包含名为render的函数。

修改视图函数,并给上述的Middleware1和Middleware2加上process_template_response方法:



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from django.shortcuts import render, HttpResponse
 2 
 3 
 4 def test(request):
 5     print('from view func')
 6     def render():
 7         print('from render')
 8     resp = HttpResponse('ok')
 9     resp.render = render
10     return resp
  • views.py



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

1 from django.utils.deprecation import MiddlewareMixin
 2 from django.shortcuts import HttpResponse
 3 
 4 
 5 class Middleware1(MiddlewareMixin):
 6     def process_request(self, request): print('from Middleware1.process_request')
 7 
 8     def process_response(self, request, response):
 9         print('from Middleware1.process_response')
10         return HttpResponse('ok')
11 
12     def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware1.process_view')
13 
14     def process_exception(self, request, exception):
15         print('from Middleware1.process_exception')
16 
17     def process_template_response(self, request, response):
18         print('from Middleware1.process_template_response')
19         return response
20 
21 
22 class Middleware2(MiddlewareMixin):
23     def process_request(self, request): print('from Middleware2.process_request')
24 
25     def process_response(self, request, response):
26         print('from Middleware2.process_response')
27         return HttpResponse('ok')
28 
29     def process_view(self, request, callback, callback_args, callback_kwargs): print('from Middleware2.process_view')
30 
31     def process_exception(self, request, exception):
32         print('from Middleware2.process_exception')
33 
34     def process_template_response(self, request, response):
35         print('from Middleware2.process_template_response')
36         return response
  • /Middleware/TestMiddleware.py



中间件 python异步队列 python中间件有哪些_django

中间件 python异步队列 python中间件有哪些_python_02

from Middleware1.process_request
from Middleware2.process_request
from Middleware1.process_view
from Middleware2.process_view
from view func
from Middleware2.process_template_response
from Middleware1.process_template_response
from render
from Middleware2.process_response
from Middleware1.process_response
  • 控制台输出: 1、中间件的process_template_response方法是在执行视图函数之后执行的。而render函数是在process_template_response方法之后process_response方法之前执行的,且仅执行一次。 2、它的执行顺序是按照MIDDLEWARE中的注册顺序从前到后倒序执行的。 3、该方法的返回值必须是HttpResponse对象。

中间件的执行流程

请求到达中间件之后,先按照注册顺序执行每个注册中间件的process_request方法,process_request方法返回的值是None,就依次执行,如果返回的值是HttpResponse对象,不再执行后面的process_request方法,而是执行当前对应中间件的process_response方法。也就是说:如下图,如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4、5、6中间件的process_request和process_response方法都不执行,顺序执行3、2、1中间件的process_response方法。

中间件 python异步队列 python中间件有哪些_中间件 python异步队列_33

process_request方法都执行完后,匹配路由,找到要执行的视图函数,先不执行视图函数,先执行中间件中的process_view方法。如果process_view方法返回None,继续按顺序执行,当所有process_view方法执行完后执行视图函数。假如中间件3 的process_view方法返回了HttpResponse对象,则4、5、6的process_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行。

中间件 python异步队列 python中间件有哪些_中间件_34

process_template_response和process_exception两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:

中间件 python异步队列 python中间件有哪些_中间件 python异步队列_35