Django中间件
1 中间件概念
- 定义: 中间件是一个与Django的请求/响应处理相关的框架。这是一个轻量级的、低级的“插件”系统,用于全局改变Django的输入或输出。
- 本质是一个类,在请求到来和结束后会根据自己发规则在合适的时机执行中间件的响应方法.
- 在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件
- 中间件可以定义四个方法:
- process_request(self,request)
- process_view(self, request, callback, callback_args, callback_kwargs)
- process_exception(self, request, exception)
- process_response(self, request, response)
返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。
2 自定义中间件
- 创建中间件类
- '''
- 与mange.py在同一目录下的文件夹 lex/middleware下的auth.py文件中的Authentication类
- '''
- class Authentication(object):
- def process_request(self,request):
- pass
- def process_view(self, request, callback, callback_args, callback_kwargs):
- i =1
- pass
- def process_exception(self, request, exception):
- pass
- def process_response(self, request, response):
- return response
- 注册中间件
- MIDDLEWARE_CLASSES = (
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
- 'lex.middleware.auth.Authentication',
- )
2.1 process_request/process_response
当用户发起请求的时候会依次经过所有的中间件中的process_request, 最后到达views的函数中, views函数处理后, 再依次经过中间件中的process_response, 最后返回给请求者.
- 示例代码:
- from django.utils.deprecation import MiddlewareMixin
- from django.shortcuts import HttpResponse
- class Md1(MiddlewareMixin):
- def process_request(self,request):
- print("Md1请求")
- def process_response(self,request,response):
- print("Md1返回")
- return response
- class Md2(MiddlewareMixin):
- def process_request(self,request):
- print("Md2请求")
- #return HttpResponse("Md2中断")
- def process_response(self,request,response):
- print("Md2返回")
- return response
- '''
- 结果:
- Md1请求
- Md2请求
- view函数...
- Md2返回
- Md1返回
- **注意**:
- 如果当请求到达请求2的时候直接不符合条件返回,即return HttpResponse("Md2中断"),程序将把请求直接发给中间件2返回,然后依次返回到请求者:
- Md1请求
- Md2请求
- Md2返回
- Md1返回
- '''
- 流程图(出现异常时):
2.2 process_view
- process_view(self, request, callback, callback_args, callback_kwargs)
- # callback 为视图函数, process_view可以用来调用视图函数
- 示例代码(1)
- from django.utils.deprecation import MiddlewareMixin
- from django.shortcuts import HttpResponse
- class Md1(MiddlewareMixin):
- def process_request(self,request):
- print("Md1请求")
- #return HttpResponse("Md1中断")
- def process_response(self,request,response):
- print("Md1返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- print("Md1view")
- class Md2(MiddlewareMixin):
- def process_request(self,request):
- print("Md2请求")
- return HttpResponse("Md2中断")
- def process_response(self,request,response):
- print("Md2返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- print("Md2view")
- '''
- 结果:
- Md1请求
- Md2请求
- Md1view
- Md2view
- view函数...
- Md2返回
- Md1返回
- '''
- 流程图
-
注意:
- 当最后一个中间的process_request到达路由关系映射之后,返回到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户。
- process_view如果有返回值,会越过其他的process_view以及视图函数,但是所有的process_response都还会执行。
-
示例代码(2)
- class Md1(MiddlewareMixin):
- def process_request(self,request):
- print("Md1请求")
- #return HttpResponse("Md1中断")
- def process_response(self,request,response):
- print("Md1返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- # return HttpResponse("hello")
- response=callback(request,*callback_args,**callback_kwargs)
- return response
- '''
- 结果:
- Md1请求
- Md2请求
- view函数...
- Md2返回
- Md1返回
- '''
2.3 process_exception
- 示例代码(无异常时):
- class Md1(MiddlewareMixin):
- def process_request(self,request):
- print("Md1请求")
- def process_response(self,request,response):
- print("Md1返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- print("md1 process_view...")
- def process_exception(self):
- print("md1 process_exception...")
- class Md2(MiddlewareMixin):
- def process_request(self,request):
- print("Md2请求")
- def process_response(self,request,response):
- print("Md2返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- print("md2 process_view...")
- def process_exception(self):
- print("md1 process_exception...")
- '''
- 结果:
- Md1请求
- Md2请求
- md1 process_view...
- md2 process_view...
- view函数...
- Md2返回
- Md1返回
- '''
- 示例代码(视图函数异常时):
- class Md1(MiddlewareMixin):
- def process_request(self,request):
- print("Md1请求")
- def process_response(self,request,response):
- print("Md1返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- print("md1 process_view...")
- def process_exception(self):
- print("md1 process_exception...")
- class Md2(MiddlewareMixin):
- def process_request(self,request):
- print("Md2请求")
- def process_response(self,request,response):
- print("Md2返回")
- return response
- def process_view(self, request, callback, callback_args, callback_kwargs):
- print("md2 process_view...")
- def process_exception(self,request,exception):
- print("md2 process_exception...")
- return HttpResponse("error")
- '''
- 结果:
- Md1请求
- Md2请求
- md1 process_view...
- md2 process_view...
- view函数...
- md2 process_exception...
- Md2返回
- Md1返回
- '''
- 流程图
2. 中间件应用案例
2.1 IP访问频率限制
某些IP访问服务器的频率过高,进行拦截,比如限制每分钟不能超过20次。
2.2 URL访问过滤
- 如果用户访问的是login视图(放过)
- 如果访问其他视图,需要检测是不是有session认证,已经有了放行,没有返回login,这样就省得在多个视图函数上写装饰器了!