Django中间件简单说明
项目主目录中的配置文件是django留给开发者使用的用户级别配置文件
实际上django有一个自己的默认全局配置文件。
那么他们的关系如下
# django默认配置 from django.conf import global_settings # 用户级别配置 from django_middleware import settings from django.conf import settings # 中间人 # 比如需要引入配置中的某个配置项settings.APPEND_SLASH,那么这样的引入的查找顺序是这样,先去用户级别settings.py文件中去找这个配合,
如果没有找到,那么会去global_settings中去找默认配置
(1)过程描述
第一步:浏览器发起请求
第二步:WSGI创建socket服务端,接收请求(Httprequest)
第三步:中间件处理请求
第四步:url路由,根据当前请求的URL找到视图函数
第五步:view视图,进行业务处理(ORM处理数据,从数据库取到数据返回给view视图;view视图将数据渲染到template模板;将数据返回)
第六步:中间件处理响应
第七步:WSGI返回响应(HttpResponse)
第八步:浏览器渲染
自定义中间件的步骤
1 在应用文件夹下面创建一个文件夹,名字随便,比如叫做mymiddleware
2 在mymiddleware文件夹下面创建一个py文件,名称随意,比如叫做middlewares.py
3 在middlewares.py文件中写上如下内容
4 在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', 'app01.mymiddleware.middelwares.LoginAuth', ]
# 配置中间件类,告诉django,我写的这个自定义中间件,你帮我使用上,一般都放到最后,不然上面几个中间件的相关功能就没办法使用上了
'app01.mymiddleware.middlewares.LoginAuth',
# 如果中间件功能不想用了,就注释它就行了
# 'app01.mymiddleware.middlewares.LoginAuth'
这样几步搞定之后,所有的请求都会触发我们的中间件类中的process_request方法。
登录认证中间件示例
中间件代码如下
# 登录认证中间件 class LoginAuth(MiddlewareMixin): # /login/登录请求,应该正常放行,让他能获得login.html页面 # 白名单、黑名单 white_list = ['/login/', ] def process_request(self,request): print('请求来啦!!!') # 获取当前请求路径:request.path /home/ # 如果当前请求的路径在白名单里面,我们不进行登录认证 if not request.path in self.white_list: is_login = request.session.get('is_login') #True if not is_login: return redirect('/login/')
视图代码如下
def login(request): if request.method == 'GET': return render(request, 'login.html') else: uname = request.POST.get('username') if uname == 'root': request.session['is_login'] = True return redirect('/home/') #告诉浏览器向/home/发送get请求获取页面 else: return redirect('/login/') def home(request): print('home') return render(request, 'home.html') def index(request): print('index') return render(request, 'index.html')
方法如下:process_request和process_response这两个是重点
-
-
process_view(self, request, view_func, view_args, view_kwargs)
-
process_template_response(self,request,response)
-
process_exception(self, request, exception)
-
针对这个五个方法,我们来看看这5个方法的执行流程。
1. process_request
class Md1(MiddlewareMixin): def process_request(self,request): print('MD1--process_request') # 当process_request返回的是None,那么才会继续执行后面的中间件的process_request,如果你是最后一个中间件,
并且你返回的是None,那么逻辑会继续执行到我们的url路由控制器 # 但是当process_request里面return的是一个HttpResponse对象,那么后面的中间件的process_request将不再执行,也不会走到url路由控制器 return HttpResponse('中间件md1的逻辑,没有通过!!!!') class Md2(MiddlewareMixin): def process_request(self, request): print('MD2--process_request')
2 process_response
class Md1(MiddlewareMixin): def process_request(self,request): print('MD1--process_request') # 当process_request返回的是None,那么才会继续执行后面的中间件的process_request,
如果你是最后一个中间件,并且你返回的是None,那么逻辑会继续执行到我们的url路由控制器 # 但是当process_request里面return的是一个HttpResponse对象,那么后面的中间件的process_request将不再执行,也不会走到url路由控制器 return HttpResponse('中间件md1的逻辑,没有通过!!!!') def process_response(self, request, response): ''' :param request: 当前请求对象 :param response: 视图函数的响应对象 :return: ''' print('Md1--响应') # print(response) #<HttpResponse status_code=200, "text/html; charset=utf-8"> # 对响应内容做统一处理 # response['xx'] = 'oo' #统一加响应头 # print(response.content) #b'ok' # 注意,如果你写了process_response方法,那么这个方法必须return response return response class Md2(MiddlewareMixin): def process_request(self, request): print('MD2--process_request') def process_response(self, request, response): print('Md2--响应') # if response.content != b'ok': # 如果process_response方法里面return了一个HttpResponse对象,这个对象会覆盖视图返回来的HttpResponse对象 # return HttpResponse('响应不ok!!!') return response
注意:当中间件1的process_request方法return的是一个HttpResponse对象,那么会执行中间件1的process_response方法,不会去执行中间件2 的方法了
3 process_view(self, request, view_func, view_args, view_kwargs):
示例代码
class Md1(MiddlewareMixin): def process_request(self,request): print('MD1--process_request') # return HttpResponse('中间件md1的逻辑,没有通过!!!!') def process_response(self, request, response): print('Md1--响应') return response def process_view(self, request, view_func, view_args, view_kwargs): print('md1---view') class Md2(MiddlewareMixin): def process_request(self, request): print('MD2--process_request') def process_response(self, request, response): print('Md2--响应') return response def process_view(self, request, view_func, view_args, view_kwargs): ''' :param request: :param view_func: 此次请求要执行的视图函数对象 :param view_args: 要函数的参数 :param view_kwargs: 要函数的参数 :return: ''' print('md2---view') # print(view_func, view_args, view_kwargs) print(view_func.__name__) # home
4 process_exception(self, request, exception)
是当试图函数出现错误或者异常时,自动触发执行的方法,能够捕获试图出现的错误,进行一些错误的统一处理
示例代码
class Md1(MiddlewareMixin): def process_request(self,request): print('MD1--process_request') # return HttpResponse('中间件md1的逻辑,没有通过!!!!') def process_response(self, request, response): print('Md1--响应') return response def process_view(self, request, view_func, view_args, view_kwargs): print('md1---view') def process_exception(self, request, exception): print('md1--exception') class Md2(MiddlewareMixin): def process_request(self, request): print('MD2--process_request') def process_response(self, request, response): print('Md2--响应') return response def process_view(self, request, view_func, view_args, view_kwargs): ''' :param request: :param view_func: 此次请求要执行的视图函数对象 :param view_args: 要函数的参数 :param view_kwargs: 要函数的参数 :return: ''' print('md2---view') # print(view_func, view_args, view_kwargs) # print(view_func.__name__) # home def process_exception(self, request, exception): from django.core.exceptions import PermissionDenied # print('>>>>>>', exception, type(exception)) # if isinstance(exception,PermissionDenied): # return HttpResponse('权限不够!!!!!') #>>>>>> 权限不够 <class 'django.core.exceptions.PermissionDenied'> # >>>>>> 出错啦!!! print('md2--exception')
视图函数示例
from django.core.exceptions import PermissionDenied def home(request): print('home') # raise Exception('出错啦!!!') raise PermissionDenied('权限不够') return render(request, 'home.html')
5 process_template_response(self,request,response)
代码示例
from django.shortcuts import render, redirect, HttpResponse from django.utils.deprecation import MiddlewareMixin class Md1(MiddlewareMixin): def process_request(self,request): print('MD1--process_request') # return HttpResponse('中间件md1的逻辑,没有通过!!!!') def process_response(self, request, response): print('Md1--响应') return response def process_view(self, request, view_func, view_args, view_kwargs): print('md1---view') def process_exception(self, request, exception): print('md1--exception') 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') def process_response(self, request, response): print('Md2--响应') return response def process_view(self, request, view_func, view_args, view_kwargs): print('md2---view') def process_exception(self, request, exception): print('md2--exception') def process_template_response(self, request, response): print("MD2 中的process_template_response") return response
视图代码
def home(request): print('home') def render(): print('你好render') return HttpResponse('你好response') ret = HttpResponse('ojbk') # 必须给HttpResponse对象封装一个render属性等于一个render函数,才能出发中间件里面的process_template_response方法 ret.render = render return ret