中间件介绍
Django中间件是django的门户。它可以用来在全局范围内改变Django的输入和输出,每个中间件都负责做一些特定的功能。
比如:全局用户身份校验,全局用户访问频率校验,用户访问黑名单。
说的直白一点:中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作
只要以后用django开发业务,设计到全局相关的功能,就可以考虑用中间件。
打开Django项目的Settings.py文件,可以看到下图的MIDDLEWARE配置项
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', ]
自定义中间件
中间件可以定义五个方法,分别是:(主要的是process_request和process_response)
- process_request(self,request)
- process_view(self, request, view_func, view_args, view_kwargs)
- process_template_response(self,request,response)
- process_exception(self, request, exception)
- process_response(self, request, response)
重要的两个方法
process_request:
它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。
由此总结一下:
- 中间件的process_request方法是在执行视图函数之前执行的。
- 当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是从上到下依次执行的。
- 不同中间件之间传递的request都是同一个对象
request_response:
多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的。
定义process_response方法时,必须给方法传入两个形参,request和response,并且需要将形参response返回。
如果你内部自己返回了HttpResponse对象 会将返回给用户浏览器的内容替换成你自己的。

class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
def process_response(self, request, response):
print("MD1里面的 process_response")
return response
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
pass
def process_response(self, request, response):
print("MD2里面的 process_response")
return response
views.py
终端输出:
MD1里面的 process_request MD2里面的 process_request app01 中的 index视图 MD2里面的 process_response MD1里面的 process_response
需要了解的三个方法
process_view
此方法是在Django路由系统匹配成功之后,视图系统之前执行的,执行顺序按照MIDDLEWARE中的注册顺序从前到后顺序执行的
process_template_response
process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法

class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
def process_response(self, request, response):
print("MD1里面的 process_response")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("-" * 80)
print("MD1 中的process_view")
print(view_func, view_func.__name__)
def process_template_response(self, request, response):
print("MD1 中的process_template_response")
return response
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
pass
def process_response(self, request, response):
print("MD2里面的 process_response")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("-" * 80)
print("MD2 中的process_view")
print(view_func, view_func.__name__)
def process_template_response(self, request, response):
print("MD2 中的process_template_response")
return response
自定义的中间件

def index(request):
print("app01 中的 index视图")
def render():
print("in index/render")
return HttpResponse("O98K")
rep = HttpResponse("OK")
rep.render = render
return rep
Views.py

MD1里面的 process_request
MD2里面的 process_request
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x000001C111B97488> index
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x000001C111B97488> index
app01 中的 index视图
MD2 中的process_template_response
MD1 中的process_template_response
in index/render
MD2里面的 process_response
MD1里面的 process_response
输出结果
process_exception
当视图函数报错的时候自动触发,它的执行顺序也是按照中间件注册顺序的倒序执行。
中间件的补充:
## 中间件 自定义中间件 ~~~ 应用下创建一个文件夹,文件夹下面创建一个xx.py文件 from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self,request): return None def process_response(self,request,response) return response ~~~ 白名单 ``` from django.urls import reverse from django.shortcuts import ( redirect,HttpResponse,render ) from django.utils.deprecation import MiddlewareMixin class SessionAuth(MiddlewareMixin): def process_request(self,request): pass #白名单 # print(request.path) white_list = [reverse('login'),'/index/'] if request.path in white_list: return None is_login = request.session.get('is_login') if is_login == True: return None else: return redirect('login') ``` # 今日内容 中间件的五个方法 ~~~ process_request(self,request) process_view(self, request, view_func, view_args, view_kwargs) process_template_response(self,request,response) process_exception(self, request, exception) process_response(self, request, response) ~~~ process_view:  process_exception:视图函数出错,会执行  process_template_response: ~~~ def index(request): print("app01 中的 index视图") #raise ValueError('出错啦') def render(): print("in index/render") #raise ValueError('出错啦') #至于render函数中报错了,那么会先执行process_template_response方法,然后执行process_exception方法,
#如果是在render方法外面报错了,那么就不会执行这个process_template_response方法了。 return HttpResponse("O98K") #返回的将是这个新的对象 rep = HttpResponse("OK") rep.render = render return rep