Django--中间件
一. 中间件
中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,全局控制django输入和输出的钩子,
钩子:功能写上就自动运行,注释就不执行该功能
# 由于是在全局上改变的,所以要慎用(高手可自行忽略这句)
django中的setting.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',
]
从上图可以看出来,按照请求的顺序,在视图函数执行之前进行一些操作,可以在中间件中搞事情, 按照响应顺序,在视图函数执行之后进行一些操作,也可以在中间件中搞事情.
# Django中用的wsgi是wsgiref是python标准库提供的模块,性能比较低,开发使用 ,性能高的是uwsgi,在进行项目部署的时候会用的到
二 . 自定义中间件
中间件可以定义五个方法: (主要是process_request和process_response)
1. process_request(self,request)
2. process_view(self,request,view_func,view_args,view_kwagrs)
3. process_template_response(self,request,response)
4. process_exception(self,request,exception)
5. process_response(self,request,response)
# 以上方法的返回值可以是None或者是HttpResponse对象, 如果是None, 则继续按照Django定义的规则向后继续执行, 如果是HttpResponse对象,则直接返回给用户.
当用户发起请求的时候会从上到下一次经过所有的中间件,这个时候的请求是process_request, 最后到达views的函数中,views处理后,再依次从下到上穿过中间件,这个时候是process_response,最后返还给请求者
自定义中间件的具体操作
1. 自己写一个类, 但是必须继承MiddlewareMinMixin
2. 在项目中创建一个包,名字一般叫utils,表示一个公用的组件,创建一个py文件.
示例
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
#自定义中间件,有request方法说明请求来了要处理,有response方法说明响应出去时需要处理,不是非要写这两个方法,
如果你没写process_response方法,那么会一层一层的往上找,哪个中间件有process_response方法就将返回对象给哪个中间件
def process_request(self, request):
print("MD1里面的 process_request")
def process_response(self, request, response):
print("MD1里面的 process_response")
return response
process_request
1.process_request有一个参数,就是request,这个request和视图函数中的request是一样的.
2.它的返回值可以是None,也可以是HttpResponse对象,返回值是None的话,按照正常流程继续走,交给下一个中间件处理,
如果是HttpResponse对象,Django将不执行视图函数,而将相应的对象返回给浏览器
多个中间件是Django执行process_request的示例
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
定义两个中间件,我们需要把它们加入到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',
'utils.middlewares.MD1', # 自定义中间件MD1,这个写的是所在路径,
'utils.middlewares.MD2' # 自定义中间件MD2
]
我们开始访问一个视图,终端打印的是:
MD1里面的 process_request
MD2里面的 process_request
app01 中的 index视图
由此可知,中间件是在视图函数之前执行,并且这个request就相当于一个接力棒一样,我用完了给你你才能用,一共就一个request.
process_response
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") #不必须写return值 def process_response(self, request, response):#request和response两个参数必须有,名字随便取 print("MD1里面的 process_response") #print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容的方法 return response #必须有返回值,写return response ,这个response就像一个接力棒一样 #return HttpResponse('瞎搞') ,如果你写了这个,那么你视图返回过来的内容就被它给替代了 class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") def process_response(self, request, response): #request和response两个参数必须要有,名字随便取 print("MD2里面的 process_response") return response #必须返回response,不然你上层的中间件就没有拿到httpresponse对象,就会报错
访问一个视图,看看终端的输出:
MD1里面的 process_request
MD2里面的 process_request
app01 中的 index视图
MD2里面的 process_response
MD1里面的 process_response
有了中间件,我们在做大量的同样的操作的时候只需要在中间件里搞一下就好,比如在做session认证的时候,不需要在用装饰器一个一个的加了,
但是这个中间件一定要放在Django自带的那个session的中间件的下面,因为我们要用到里面功能. 一定要注意放的顺序
session认证的中间件示例
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse,redirect,render from django.urls import reverse class M1(MiddlewareMixin): def process_request(self, request): #设置路径白名单,只要访问的是login登陆路径,就不做这个session认证 if request.path in [reverse('login'),]: return None # 继续往下执行 else: ret = request.session.get('session_login') if ret: return None else: return redirect(reverse('login')) def process_response(self, request, response): print('M1响应部分') # print(response.__dict__['_container'][0].decode('utf-8')) return response
process_view
process_view(self, request, view_func, view_args, view_kwargs)
参数分别代表的意义
1. request 是HttpRequest对象.
2. view_func 就是你在网页上输入网址,然后url调用的那个函数
3. view_args 是将要传递给视图函数的位置参数列表
4. view_args 是将要传递给视图的关键字参数的字典
# Django会在调用视图函数之前调用process_view方法
process_exception
process_exception(self, request, exception)
参数的意义
1. request 是HttpResponse对象
2. exception 是视图函数异常产生的Exception对象.
# 这个方法只有在视图函数出现异常才执行, 他的返回值可以是None或者是HttpResponse对象,
如果返回的是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,
如果返回的是None,将交给下一个中间件的process_exception方法来处理,执行顺序是注册顺序的倒序,
如果都没有返回HttPResponse对象,那么Django就会给你返回一个,就是那个大黄页.
process_template_response(用的比较少)
process_template_response(self,request,response)
request是HttpResponse对象
response是TemplateResponse对象(由视图函数或者中间件产生)
# process_template_response是在视图函数执行完成后立即执行,在模板渲染之前,
但是他有一个前提条件,就是视图函数返回的对象有一个render()方法(或者表明该对象是TemplateResponse对象或等价方法)