Django之Middleware(中间件)

中间件

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

  在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件(内置) 

  详细:https://docs.djangoproject.com/en/2.2/ref/middleware/#security-middleware 

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 ]

  中间件中可以定义五个方法,分别是:

  • process_request(self,request)
  • process_view(self, request, callback, callback_args, callback_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

  以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

Django的请求生命周期如图:

 自定义中间件

创建中间件类

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 from django.shortcuts import HttpResponse
 5 from django.utils.deprecation import MiddlewareMixin
 6 
 7 
 8 class M1(MiddlewareMixin):
 9 
10     def process_request(self, request):
11         """
12         内部已经帮我们返回
13         如果我们自己加上返回值,在1.1版本前直接在当前中间件的process_response方法返回
14         在1.7 1.8版本后要跳到最后一个中间件的process_response方法一层层的返回
15         :param request:
16         :return:
17         """
18         print('m1.process_request')
19 
20     def process_view(self, request, callback, callback_args, callback_kwargs):
21         """
22         得到当前请求的执行视图函数名字
23         :param request:
24         :param callback:
25         :param callback_args:
26         :param callback_kwargs:
27         :return:
28         """
29         print('m1.process_view')
30         print(callback)
31         # 如果这里执行callback(就是视图函数的名字)函数,下面每一个中间件的process_view方法都不走了,直接返回执行视图函数的结果
32         # 如果这里不执行callback视图函数方法,那么继续走下面中间件的process_view,如果都没执行(这里又有加装饰器的作用了,
33         # 如果视图函数要加装饰器,那么这里加上装饰器)再走路由匹配,这样为视图函数巧妙的加上装饰器了
34 
35         # response = callback(request, *callback_args, **callback_kwargs)
36         # return response
37 
38     def process_response(self, request, response):
39         """
40         在这个环节已经通过了路由系统执行当前请求的视图函数了,一层层的返回字符串给用户
41         :param request:
42         :param response:
43         :return:
44         """
45         print('m1.process_response')
46         return response
47 
48     def process_exception(self, request, exception):
49         print('m1.process_exception')
50 
51     def process_template_response(self, request, response):
52         """
53         视图函数的返回值如果有render方法,才触发这个函数执行
54         :param request:
55         :param response:
56         :return:
57         """
58         print('m1.process_template_response')
59         return response
60 
61 
62 class M2(MiddlewareMixin):
63 
64     def process_request(self, request):
65         print('m2.process_request')
66 
67     def process_view(self, request, callback, callback_args, callback_kwargs):
68         print('m2.process_view')
69 
70     def process_response(self, request, response):
71         print('m2.process_response')
72         return response
73 
74     def process_exception(self, request, exception):
75         print('m2.process_exception')

注册中间件

 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     'md.M1',
10     'md.M2',
11 ]

 1.路由

urlpatterns = [
    path('index/', views.index),
]

2.视图

 1 from django.shortcuts import render, HttpResponse
 2 
 3 
 4 class Foo:
 5     def __init__(self, request, status, message):
 6         self.request = request
 7         self.status = status
 8         self.message = message
 9 
10     def render(self):
11         import json
12         result = {
13             'status': self.status,
14             'message': self.message
15         }
16         return HttpResponse(json.dumps(result))
17 
18 
19 def index(request):
20     # print('index执行视图函数')
21     # return HttpResponse('.........')
22     return Foo(request, True, "错误信息")

我把几个函数都写在一起分步骤测试的  测试如下图:(正常情况如上图请求生命周期,process_exception和process_template_response如下)  

上图测试的process_exception

总结下process_exception方法触发的机制流程图:

下图是测试process_template_response:

 

总结下process_template_response:视图函数的返回值如果有render方法,才触发这个函数执行

总结:

     中间件是有序的,从上到小依次执行,本质是因为一个列表

    应用:如果要对请求批量操作的时候就用中间件做

    0.对用户请求缓存中有,我就直接给你,没有就执行视图后续操作(从内存拿数据比从磁盘快多了嘛)

    1.做黑名单

    2.对所有请求日志的记录

    3.做认证权限

    4.装饰器局部使用,全局使用啊

    5.自己也可以做csrf_token认证

      等等很多的看需求

原文地址:https://www.cnblogs.com/Alexephor/p/11272839.html