中间件
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认证
等等很多的看需求