自定义Django中间件的方式
Django 自定义中间件
Django 中间件是一个轻量级、底层的插件系统,可以介入 Django 的请求和响应处理过程,修改 Django 的输入或输出。
定义 Django 中间有以下几种方式:
- 定义中间件工厂函数
- 定义中间件类
- 定义中间件子类, 继承自
MiddlewareMixin
工厂函数
def simple_middleware(get_response):
print('第一次配置和初始化的时候执行一次')
def inner(request):
print('每个请求处理视图前被执行')
response = get_response(request)
print('每个请求处理视图之后被执行')
return response
return inner
类
class MyMid:
def __init__(self, get_response):
self.get_response = get_response
print('first init')
def __call__(self, *args, **kwargs):
print('MyMid: process request')
response = self.get_response(*args, **kwargs)
print('MyMid: process response')
return response
子类
子类可实现的方法:
- process_request
- process_view
- process_response
- process_template_response
- process_exception
继承自 MiddlewareMixin
, 不必写 __call__
和 __init__
方法。
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class MyMiddleware(MiddlewareMixin):
def process_request(self, request):
"""Request 预处理方法.
Return:
None --> 交给下一个中间件继续处理
HttpResponse() --> 不再执行任何其它的中间件以及相应的 view, 立即返回该 HttpResponse
"""
print(request.path)
print('process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
"""View 预处理方法.
Return:
None --> Django 将继续处理这个 request, 执行后续的中间件, 然后调用相应的 view
HttpResponse() --> Django 将不再执行任何其它的中间件以及相应的 view, 立即返回
"""
print('process_view')
return None
# return response
def process_response(self, request, response):
"""Response 后处理方法.
Return:
必须返回 HttpResponse 对象.
可以新生成一个 HttpResponse 对象来返回
"""
print('process_response')
return response
def process_template_response(self, request, response):
"""在模板渲染前执行.
Return:
返回实现了 render 方法的响应对象
"""
print('process_template_response')
return response
def process_exception(self, request, exception):
"""Exception 后处理方法.
Return:
None --> Django 将用框架内置的异常处理机制继续处理相应 request
HttpResponse() --> Django 将使用该 response,而短路框架内置的异常处理机制
"""
print('process_exception')
print('log: ', exception)
return HttpResponse('Emm, Error!')
注册中间件
"""settings.py"""
MIDDLEWARE = [
# ...
# 根据实际情况修改路径
'middlewares.mid_test1.MyMiddleware',
'middlewares.mid_test2.MyMid',
'middlewares.mid_test3.simple_middleware',
]
测试中间件方法的调用时机
创建一个 demo 项目, 然后创建一个 app1 应用, 写好主路由和子路由, 建好模板文件, 定义以下视图。
# demo/app1/views.py
from django.http import HttpResponse
from django.template.response import TemplateResponse
def index(request):
"""
访问视图对应路由时, 类中间件方法的打印顺序:
process_request
process_view
process_response
"""
return HttpResponse('Hello index.')
def exc(request):
"""
访问视图对应路由时, 类中间件方法的打印顺序:
process_request
process_view
process_exception
process_response
"""
raise
def template(request):
"""
访问视图对应路由时, 类中间件方法的打印顺序:
process_request
process_view
process_template_response
process_response
"""
# 注: 返回 render 结果时不会走类中间件的 process_template_response,
# 要测试它, 需要返回 TemplateResponse()
# return render(
# request,
# 'app1/test.html',
# context={'data': 'Hello template.'}
# )
return TemplateResponse(
request,
'app1/test.html', # 去找 demo/app1/templates/app1/test.html
context={'data': 'Hello template.'}
)
中间件的执行顺序
多个中间件的执行顺序
- 在请求视图被处理前,中间件由上至下依次执行
- 在请求视图被处理后,中间件由下至上依次执行