Django之中间件(十三)
一、中间件介绍
1.1 中间件简介
django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。
在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件
中间件共分为:
process_request(self,request) process_view(self, request, callback, callback_args, callback_kwargs) process_template_response(self,request,response) process_exception(self, request, exception) process_response(self, request, response)
中间件顺序:
中间件是嵌入 django 的 request/response 处理过程的一套钩子框架。它是一个轻量级的底层嵌入系统,可以对 django 的输入输出做整体的修改。
也就是说,每一个请求都是先通过中间件中的 process_request 函数,这个函数返回 None 或者 HttpResponse 对象,如果返回前者,继续处理其它中间件,如果返回一个 HttpResponse,就处理中止,返回到网页上。
中间件不用继承自任何类(可以继承 object ),下面一个中间件大概的样子:
class CommonMiddleware(object): def process_request(self, request): return None def process_response(self, request, response): return response
使用方法 :
Django中间件必须是一个类,不需要继承任何类,并提供四个接口:
process_request(self, request)该方法在请求到来的时候调用。 process_view(self ,request, fnc , arg ,kwarg)在本次将要执行的View函数被调用前调用本函数。 process_response(self,request,response)在执行完View函数准备将响应发到客户端前被执行。 **process_exception(self,request, exception)**View函数在抛出异常时该函数被调用,得到的exception参数是实际上抛出的异常实例。通过此方法可以进行很好的错误控制,提供友好的用户界面。
二、自定义中间件
2.1 中间件之process_request,process_response
process_request(self,request)
process_response(self, request, response)
当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者
在django中叫中间件,在其他web框架中,有的叫管道,httphandle
创建自定义类
我们可以自己写一个类,但是必须继承MiddlewareMixin。所以需要导入:from django.utils.deprecation import MiddlewareMixin
我们在项目文件下创建一个Middle目录,并在下面创建m1.py代码例子如下:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class Row1(MiddlewareMixin): def process_request(self,request): print('中间件1请求') def process_response(self, request, response): print('中间件1返回') return response class Row2(MiddlewareMixin): def process_request(self,request): print('中间件2请求') # return HttpResponse('走') def process_response(self, request, response): print('中间件2返回') return response class Row3(MiddlewareMixin): def process_request(self,request): print('中间件3请求') def process_response(self, request, response): print('中间件3返回') return 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', 'Middle.m1.Row1', #在这里添加就是注册中间件,这就定位到了Middle目录下的m1下的Row1 'Middle.m1.Row2', 'Middle.m1.Row3', ]
其他设置:
urls.py:
url(r'^test/$', views.test),
views.py:
def test(request): print('中间件测试') return HttpResponse('OK')
测试一下:
#前端url访问以下:http://127.0.0.1:8000/test/
#从上图可以看到,用户有访问请求,会从中间件最上方的request(接收)一直往下执行,最后到视图函数然后再由中间件从下往上的response(返回)给用户。
2.2 中间件之process_view
创建自定义类:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class Row1(MiddlewareMixin): def process_request(self,request): print('中间件1请求') def process_view(self, request, view_func, view_func_args, view_func_kwargs): print('中间件1view') def process_response(self, request, response): print('中间件1返回') return response class Row2(MiddlewareMixin): def process_request(self,request): print('中间件2请求') # return HttpResponse('走') def process_view(self, request, view_func, view_func_args, view_func_kwargs): #view_func, view_func_args, view_func_kwargs都是views函数里面的参数 print('中间件2view') def process_response(self, request, response): print('中间件2返回') return response class Row3(MiddlewareMixin): def process_request(self,request): print('中间件3请求') def process_view(self, request, view_func, view_func_args, view_func_kwargs): print('中间件3view') def process_response(self, request, response): print('中间件3返回') return response def process_exception(self, request, exception): #对views的报错做特殊处理。当出错的时候会执行这里 if isinstance(exception,ValueError): #当出现isinstance这个错误的时候,就返回下面的内容 return HttpResponse('出现异常》。。') def process_template_response(self,request,response): #默认也是不执行的,如果Views中的函数返回的对象中,具有render方法 print('-----------------------') return response
#可以看到request完事之后又折回来执行view,然后再到views函数返回,然后再是response。
views.py函数也改一改:
class Foo: def __init__(self,req,html,dic): self.req = req self.html = html self.dic = dic def render(self): # // 创建钩子 return render(self.req,self.html,self.dic) def test(request,nid): print('中间件测试') # return render(request, 'index.html', {...}) return Foo(request, 'index.html', {'k1': 'v1'})