中间件

之前我们说django的生命周期:url ->  路由系统  ->函数或者类 -> 返回字符串 或者 模板语言,其实前面还有很多的操作。

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

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

settings.py

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 ]

 执行过程:

请求要从中间件穿过,然后返回的时候再从中间件穿出。

自定义中间件

1、创建中间件类

 创建一个目录Middle,下面写一个m1.py:

 1 from django.utils.deprecation import MiddlewareMixin
 2 
 3 class Row1(MiddlewareMixin):
 4     def process_request(self,request):
 5         print("first...")
 6 
 7 class Row2(MiddlewareMixin):
 8     def process_request(self,request):
 9         print("second...")
10 class Row3(MiddlewareMixin):
11     def process_request(self,request):
12         print("third...")

2、注册中间件

 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     'Middle.m1.Row1',
10     'Middle.m1.Row2',
11     'Middle.m1.Row3',
12 ]

 

 view.py:

1 def test(request):
2     print("返回的信息。。。")
3     return HttpResponse('ok')

我们运行,返回的结果是:

这个请求是经过中间件中所有的process_request方法,那也应该有一个response

 1 from django.utils.deprecation import MiddlewareMixin
 2 
 3 class Row1(MiddlewareMixin):
 4     def process_request(self,request):
 5         print("first...")
 6     def process_response(self,request,response):
 7         print("first response")
 8         return response
 9 
10 class Row2(MiddlewareMixin):
11     def process_request(self,request):
12         print("second...")
13     def process_response(self,request,response):
14         print("second response")
15         return response
16 
17 class Row3(MiddlewareMixin):
18     def process_request(self,request):
19         print("third...")
20     def process_response(self,request,response):
21         print("third response")
22         return response

 我们要注意,process_response中的参数request,response的名字和顺序都不能够错,否则就会出现错误。

那现在我们来看看我们运行的效果是什么样子的 :

那这个就是中间件执行的顺序过程。

那中间件有什么用呢?

我们可以看到这个参数有request和response,那这个request就是view中的函数中的参数request,我们通过它可以获得method,post值等。所以我们可以做这个样的事情:判断一下发来请求有没有带请求头,如果没有带请求头,那就不需要继续往下走了,直接在中间件中就停止。

比如:我们上面的三个中间件,我们的请求经过了第一个Row1,下面到Row2,如果我们在这里面做一个判断:如果没有带请求头的话就直接return,我们看看怎么执行的? 

1 from django.shortcuts import HttpResponse
2 class Row2(MiddlewareMixin):
3     def process_request(self,request):
4         print("second...")
5         return HttpResponse("停止")
6     def process_response(self,request,response):
7         print("second response")
8         return response

 你看,这个就直接跳过了third,然后返回

 

这个就是整个请求周期,我们可以发现在前面还有一大堆的东西挡着,这个中间件适合于对所有的请求进行一个统一的操作,如公共校验,黑名单过滤:获取一下用户的ip,如果在黑名单里就不让它访问,直接在中间件中组织了,没有必要执行下面的操作。

process_view(self, request, callback, callback_args, callback_kwargs)

我们现在在上面的中间件中在加入一个方法process_view:

 1 from django.utils.deprecation import MiddlewareMixin
 2 
 3 class Row1(MiddlewareMixin):
 4     def process_request(self,request):
 5         print("first...")
 6 
 7     def process_view(self, request, view_func, view_func_args, view_func_kwargs):
 8         print("first process_view")
 9 
10     def process_response(self,request,response):
11         print("first response")
12         return response
13 
14 from django.shortcuts import HttpResponse
15 class Row2(MiddlewareMixin):
16     def process_request(self,request):
17         print("second...")
18 
19     def process_view(self, request, view_func, view_func_args, view_func_kwargs):
20         print("second process_view")
21 
22     def process_response(self,request,response):
23         print("second response")
24         return response
25 
26 class Row3(MiddlewareMixin):
27     def process_request(self,request):
28         print("third...")
29 
30     def process_view(self, request, view_func, view_func_args, view_func_kwargs):
31         print("third process_view")
32 
33     def process_response(self,request,response):
34         print("third response")
35         return response

 下面我们再来看看执行的结果:

由上面的显示结果我们可以看到的运行流程是,先执行process_request,匹配了url路由之后,折回来在执行process_view,执行views.py中的函数,之后再执行process_response

 process_view里面的参数实际上就是views.py里面的函数的函数名和参数,如果我们在url中添加的是正则匹配,那后面就要用一个参数接收一下。

 process_exception(self, request, exception)如果views中的函数执行错误了就执行该方法

 m1.py

 1 class Row3(MiddlewareMixin):
 2     def process_request(self,request):
 3         print("third...")
 4 
 5     def process_view(self, request, view_func, view_func_args, view_func_kwargs):
 6         print("third process_view")
 7 
 8     def process_response(self,request,response):
 9         print("third response")
10         return response
11     def process_exception(self, request, exception):
12         if isinstance(exception,ValueError):
13             return HttpResponse("出现异常了。。。。")

 views.py:

1 def test(request):
2     int("asdfasdf")
3     print("返回的信息。。。")
4     return HttpResponse('ok')

 上面的views.py中的函数很明显有一个错误,如果正常情况下执行肯定会报错,但是我们在中间件中进行了处理,那么我们在执行的时候就会返回一个出现异常。。。。

所以这个东西就可以对异常,报错进行处理,但是如果views.py中没有出错,那么就不会被执行

process_template_response(self,request,response)

 默认也不执行,如果views中的函数返回的对象中,具有render方法,那就默认会执行

views.py:

1 class Foo:
2     def render(self):
3         return HttpResponse("ok")
4 def test(request):
5 
6     print("返回的信息。。。")
7     return Foo()

 

m1.py:

 1 class Row3(MiddlewareMixin):
 2     def process_request(self,request):
 3         print("third...")
 4 
 5     def process_view(self, request, view_func, view_func_args, view_func_kwargs):
 6         print("third process_view")
 7 
 8     def process_response(self,request,response):
 9         print("third response")
10         return response
11     def process_exception(self, request, exception):
12         if isinstance(exception,ValueError):
13             return HttpResponse("出现异常了。。。。")
14     def process_template_response(self,request,response):
15         print("process_template_response函数执行")
       return response

运行结果: