django --中间件
中间件
中间件事一个钩子框架,它们可以介入Django的请求和响应处理过程.用于在全局修改Django 的输入或输出。每个中间件组件负责完成某个特定的功能
激活中间件
要激活一个中间件组件,需要把它添加到django配置文件中的MIDDLEWARE中,每一个中间件组件用字符串的方式描述:一个完整的python全路径加上中间件的类名称.
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',
]
在请求阶段,调用视图之前,Django会按照MIDDLEWARE中定义的顺序自顶向下应用中间件,会用到两个钩子process_request()和process_view()
在响应阶段,调用视图之后,中间件会按照相反的顺序应用,自底向上,会用到三个钩子process_exception()(仅当视图抛出异常的时候)process_template_response()(仅用于模板响应)和process_response()
下图是请求过来之后以及响应的流程图



编写自己的中间件
#这个文件是自己写的中间件文件 from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse # 在process_request中没有return的情况 # 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请求") # # def process_response(self,request,response): # print("Md2响应") # return response ''' 上面代码的执行结果是:Md1请求-->Md2请求--->views index的视图函数-->Md2响应->Md1响应 客户端发出请求之后,请求首先是在wsgi中进行数据的分析,然后进入到中间件中从头到尾执行process_request 中的代码,然后再执行视图函数,然后又在中间件中从尾到头执行process_response ''' # 中间件process_request中有return的情况 # class Md1(MiddlewareMixin): # def process_request(self,request): # print("Md1请求") # # return HttpResponse("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请求-->Md2响应-->Md1响应 执行顺序是:浏览器请求发送过来之后先是在wsgi进行处理,然后进入到中间件中开始从头执行process_request, 一旦在process_request中有return 返回值,这个返回值就会作为参数传给正在执行的这个中间件中的 process_response,然后process_response执行完之后把新的返回值以当前执行的中间件为开始到第一个执行的中间件 为结束执行process_response,然后又经过wsgi进行处理之后发送给浏览器 所以这个请求并没有执行到视图函数,在中间件中时就被中断了,返回的响应也是中间件中的返回值 ''' # process_view函数是在进行路由分发之后处理视图函数之前执行的,执行顺序也是在中间件中从头到尾执行 # 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("Md1 process_view", callback, callback_args, callback_kwargs) # res=callback(request) # return res # 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("Md2 process_view",callback) ''' process_view中没有调用callback时:(callback指的是url中路由分发的函数名index) 上面代码的执行结果是:Md1请求-->Md2请求-->Md1 process_view <function index at 0x00000235601DAB70>---> Md2 process_view <function index at 0x00000235601DAB70>-->views index的视图函数-->Md2响应-->Md12响应 代码的执行顺序是:浏览器发送请求-->中间件从头到尾执行process_request-->(process_request中没有返回值的情况下)执行urls 中的路由分发-->中间件中从头到尾执行process_view,-->执行视图函数-->中间件从尾到头执行process_response process_view中调用callback时: 执行结果是:Md1请求-->Md2请求-->Md1 process_view <function index at 0x00000235601DAB70>---> views index的视图函数-->Md2响应-->Md12响应. 代码的执行顺序是:浏览器发送请求-->中间件从头到尾执行process_request-->(process_request中没有返回值的情况下)执行urls 中的路由分发-->中间件中从头到尾执行process_view,执行过程中一旦某个中间件中调用了callback,把响应信息作为参数传给最后一个中间件中 的process_response,-->中间件从尾到头执行process_response.这个过程就不会再执行视图函数了,因为视图函数在process_view中被调用了 ''' #process_exception是捕获视图函数执行过程中是否有报错,参数exception就是视图函数执行中的报错信息 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("Md1 process_view", callback, callback_args, callback_kwargs) # res=callback(request) # return res def process_exception(self,request,exception): print("Md1 process_exception") 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("Md2 process_view",callback) def process_exception(self,request,exception): print("Md2 process_exception") return HttpResponse(exception) ''' process_exception中没有返回值时: 上面代码的执行结果:Md1请求 ->Md2请求 ->Md1 process_view <function index at 0x000002162F8DAB70> ->Md2 process_view <function index at 0x000002162F8DAB70> ->views index的视图函数 ->Md2 process_exception ->Md1 process_exception ->Md2响应 ->Md1响应 代码执行顺序是:浏览器请求-->wsgi-->中间件从头到尾执行process_request-->(请求中没有返回值时)urls--> 从头到尾执行process_view-->(process_view中没有调用callback时)视图函数-->中间件中从尾到头执行process_exception -->中间件从尾到头执行process_response -->wsgi -->浏览器接收响应 process_exception中有返回值时: 上面代码的执行结果:Md1请求 ->Md2请求 ->Md1 process_view <function index at 0x000002162F8DAB70> ->Md2 process_view <function index at 0x000002162F8DAB70> ->views index的视图函数 ->Md2 process_exception -->Md2响应-->Md1响应 代码执行顺序是:浏览器请求-->wsgi-->中间件从头到尾执行process_request-->(请求中没有返回值时)urls--> 从头到尾执行process_view-->(process_view中没有调用callback时)视图函数-->中间件中从尾到头执行process_exception(一旦捕获到错误信息) 就可以把错误信息返回,这样网页上就不会有报错的网页,当然也可以返回自定义错误信息 -->中间件从尾到头执行process_response -->wsgi-->浏览器接收响应 '''
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', 'my_middleware.Md1', 'my_middleware.Md2', ]
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',views.index), ]
def index(request): print("views index的视图函数") # print(name) #在视图函数中抛出异常,目的是让中间件中的process_exception捕获 return HttpResponse("ok")

浙公网安备 33010602011771号