介绍
- A middleware is a callable that takes a request and returns a response, just like a view。
- 位于wsgi和路由映射之间的一个模块,能够在全局上改变django的输入与输出,例如用户信息验证/日志记录等。
Django的中间键类型分为五种:
- 请求(Request)中间件 -> 对应函数
process_request
- 视图(View)中间件 -> 对应函数
process_view
- 模板(Template)中间件 -> 对应函数
process_template_response
- 响应(Response)中间件 -> 对应函数
process_response
- 异常(Exception)中间件 -> 对应函数
process_exception
- 请求(Request)中间件 -> 对应函数
中间件执行流程示意图
自定义中间件
步骤
1、在项目目录下创建文件夹utils
, 内部创建my_middleware.py
文件,文件名称和类名称自定义;
from django.utils.deprecation import MiddlewareMixin
class Md1(MiddlewareMixin):
def process_request(self, reqeust):
print('md1_process_request')
def process_response(self, requst, response):
print('md1_process_response')
return response # 必须带返回值
def process_view(self, request, callback, callback_args, callback_kwargs):
print("中间件1view")
class Md2(MiddlewareMixin):
def process_request(self, request):
print('md2_process_request')
def process_response(self, request, response):
print('md2_process_response')
return response # 必须带返回值
def process_view(self, request, callback, callback_args, callback_kwargs):
print("中间件2view")
2、在配置文件中加入加上的中间件:
MIDDLEWARE = [
'utils.my_middleware.Md1',
'utils.my_middleware.Md2',
]
3、此时django所有的请求和相应都会依次经过process_request()
和process_response
函数.
md1_process_request
md2_process_request
md2_process_response
md1_process_response
process_request返回值
- 默认为
return None
- 当需要过滤某些请求时,可以直接
return
- 若存在返回值,就不会继续往下执行,就地返回相应的返回值至浏览器。
from django.shortcuts import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class Md1(MiddlewareMixin):
def process_request(self, request):
print('md1_process_request')
return HttpResponse('<h1>你好</h1>')
# 打印结果
md1_process_request
md1_process_response
process_response返回值
- 返回值就是HttpResponse返回的字符串,返回的字符串会经过中间件处理;
- 例如加上响应头数据,必须带返回值, 否则会出现系统错误.
为提高兼容性,
- 直接在自定义的Md上方写入以下源码,直接继承。
- 此时就无须导入(有时候版本不同, 文件位置会有变动)
class MiddlewareMixin(object):
def __init__(self, get_response=None):
self.get_response = get_response
super(MiddlewareMixin, self).__init__()
def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response
自定义中间件实现用户登录
# my_middleware.py
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render
class Md1(MiddlewareMixin):
def process_request(self, request):
print('md1_process_request')
# 若本次请求是login页面, 则当前中间件不做任何操作
if request.path == '/login.html':
return None
# 若未取不到对应的信息,则跳转至登录页面,此处直接render
if not request.session.get('user_info'):
return render(request, 'login.html')
def process_response(self, request, response):
print('md1_process_response')
return response # 必须带返回值
注意事项
- 在配置文件中,自定制中间件尽可能放在尾部,因为必须经过django自带的中间件处理再进行自定义操作
- 注意重定向的问题,若取不到session信息就直接redirect登录url的话,就会出现无限从定向问题,因为下一次回到这里还是没有session信息,所以直接render页面,避免此问题。
process_view方法
- 到达路由映射匹配视图函数时又再一次由上到下运行每个中间件的
process_view
方法 process_view
函数默认return None
- 若带返回值的话,那么后面中间件的
process_view
都不会执行,直接跳转到尾部执行process_response
, 返回值为process_view
的返回值