文章目录
- 1. 中间件执行流程
- 2. 中间件原理浅析
- 3. 中间件的应用
Django 1.10之前,请求到达第一个中间件,会找到最后一个中间件的 process_response 返回:
而Django 1.10之后,会找到自己的 process_response 返回:
中间件是有序执行的!
中间件是类,首先查看Django源码中的中间件:
所以,我们写的中间件也要继承MiddlewareMixin类,这里把中间件类写在middleware.py,并放置在与manage.py同级目录下:
middleware.py:
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
def process_request(self, request):
print('m1.process_request')
def process_response(self, request, response):
print('m1.process_response')
return response
class M2(MiddlewareMixin):
def process_request(self, request):
print('m2.process_request')
def process_response(self, request, response):
print('m2.process_response')
return response
"""
m1.process_request
m2.process_request
test
m2.process_response
m1.process_response
"""
还要在配置文件 settings.py
中注册中间件:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'middleware.M1',
'middleware.M2'
]
可以看到 先执行process_request再执行process_response
。还有个process_view方法:
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
def process_request(self, request):
print('m1.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
print('m1.process_view')
# return callback(*callback_args, **callback_kwargs)
def process_response(self, request, response):
print('m1.process_response')
return response
class M2(MiddlewareMixin):
def process_request(self, request):
print('m2.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
print('m2.process_view')
# return callback(*callback_args, **callback_kwargs)
def process_response(self, request, response):
print('m2.process_response')
return response
"""
m1.process_request
m2.process_request
m1.process_view
m2.process_view
test
m2.process_response
m1.process_response
"""
process_request有返回值会直接执行自己的process_response。如果执行的是process_view有返回值,会跳过下一个中间件的process_view,执行视图函数(这里是自动调用的
)。接下来,不是执行自己的process_response返回给用户,而是 最开始
的process_response(把所有的process_response都执行一遍
):
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
def process_request(self, request):
print('m1.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
# print(callback, callback_args, callback_kwargs) # () {}
print('m1.process_view')
response = callback(request, *callback_args, **callback_kwargs)
return response
def process_response(self, request, response):
print('m1.process_response')
return response
class M2(MiddlewareMixin):
def process_request(self, request):
print('m2.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
print('m2.process_view')
def process_response(self, request, response):
print('m2.process_response')
return response
"""
m1.process_request
m2.process_request
m1.process_view
test
m2.process_response
m1.process_response
"""
中间件的类中还有 process_exception 方法,这是关于异常的方法。为了进行测试首先在视图函数中使代码产生异常:
def test(request):
print('test')
a = int('erics')
return HttpResponse()
通过下面的代码测试发现,请求经过所有的process_request、process_view到达视图函数,没有错误的情况下会执行process_response,出现错误会执行process_exception在执行process_response:
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
def process_request(self, request):
print('m1.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
# print(callback, callback_args, callback_kwargs) # () {}
print('m1.process_view')
# response = callback(request, *callback_args, **callback_kwargs)
# return response
#
def process_response(self, request, response):
print('m1.process_response')
return response
def process_exception(self, request, exception):
print('m1.process_exception')
class M2(MiddlewareMixin):
def process_request(self, request):
print('m2.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
print('m2.process_view')
def process_response(self, request, response):
print('m2.process_response')
return response
def process_exception(self, request, exception):
print('m2.process_exception')
"""
m1.process_request
m2.process_request
m1.process_view
m2.process_view
test
m2.process_exception
m1.process_exception
m2.process_response
m1.process_response
"""
在process_exception使用HttpResponse函数返回异常,可以看这个时候中间件方法的执行顺序:
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class M1(MiddlewareMixin):
def process_request(self, request):
print('m1.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
# print(callback, callback_args, callback_kwargs) # () {}
print('m1.process_view')
# response = callback(request, *callback_args, **callback_kwargs)
# return response
#
def process_response(self, request, response):
print('m1.process_response')
return response
def process_exception(self, request, exception):
print('m1.process_exception')
class M2(MiddlewareMixin):
def process_request(self, request):
print('m2.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
print('m2.process_view')
def process_response(self, request, response):
print('m2.process_response')
return response
def process_exception(self, request, exception):
# print('m2.process_exception')
return HttpResponse('出现异常!')
"""
m1.process_request
m2.process_request
m1.process_view
m2.process_view
test
m2.process_response
m1.process_response
"""
异常被M2的process_exception处理了,跳过M1的process_exception,直接执行process_response。页面也不没有报错了:
中间件中还有process_template_response方法,但是这个方法在视图函数的返回值中有render方法才会执行,没有render方法不会被执行,所以这里修改视图函数:
class Foo:
def __init__(self, req):
self.req = req
def render(self):
return HttpResponse()
def test(request):
obj = Foo(request)
return obj
接下来可以看到process_template_response方法被执行,
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class M1(MiddlewareMixin):
def process_request(self, request):
print('m1.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
print('m1.process_view')
def process_response(self, request, response):
print('m1.process_response')
return response
def process_exception(self, request, exception):
print('m1.process_exception')
def process_template_response(self, request, response):
"""
视图函数的返回值中有render方法才会执行
:param request:
:param response:
:return:
"""
print('m1.process_template_response')
return response
class M2(MiddlewareMixin):
def process_request(self, request):
print('m2.process_request')
def process_view(self, request, callback, callback_args, callback_kwargs):
print('m2.process_view')
def process_response(self, request, response):
print('m2.process_response')
return response
def process_exception(self, request, exception):
return HttpResponse('出现异常!')
def process_template_response(self, request, response):
print('m2.process_template_response')
return response
"""
m1.process_request
m2.process_request
m1.process_view
m2.process_view
m2.process_template_response
m1.process_template_response
m2.process_response
m1.process_response
"""
process_template_response方法的使用,可以帮助我们把一些可以复用的功能组件拆分出来,如JSON序列化:
class Foo:
def __init__(self, req, status, msg):
self.req = req
self.status = status
self.msg = msg
def render(self):
import json
ret = {
'status': self.status,
'msg': self.msg
}
return HttpResponse(json.dumps(ret))
def test(request):
return Foo(request, True, '错误信息!')
在视图函数中打造功能,改造另外一个对象,让这个对象把我们的数据封装起来:
class JsonResponse:
"""
内部帮助我们序列化,
"""
def __init__(self, req, status, msg):
self.req = req
self.status = status
self.msg = msg
def render(self):
import json
ret = {
'status': self.status,
'msg': self.msg
}
return HttpResponse(json.dumps(ret))
def test(request):
return JsonResponse(request, True, '错误信息!')
视图函数返回的对象且对象中有render方法才会执行process_template_response方法。
中间件可以对 所有请求或一部分请求做批量处理
。使用缓存时,需要对 所有请求进行判断
,缓存中如果有就把缓存中的数据返回,没有就执行视图函数。对所有的请求进行判断就需要使用到中间件。