目录
一、中间件 - 介于request(请求)与response(响应)处理之间的一道处理过程
3-1 process_request、process_response - 请求响应方法
3-2-1 process_view 返回为 None 的情况下照常执行
3-2-2 process_view 有返回值, 过其他的process_view以及视图函数
3-3 process_exception - 视图函数中出现异常,执行方法
3-4 process_template_response(self,request,response) - 视图函数的返回值是含有render方法类的对象时,调用方法
一、中间件 - 介于request(请求)与response(响应)处理之间的一道处理过程
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能
Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.
1-1 中间件的意义和功能
如果你想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现。
可能你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现。
''' Django默认的中间件: 在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件 ''' 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', ]
二、 自定义中间件
结果:
- 导入模块 - 必须继承MiddlewareMixin
from django.utils.deprecation import MiddlewareMixin
class MiddlewareMixin: def __init__(self, get_response=None): self.get_response = get_response super().__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): response = self.process_request(request) response = response or self.get_response(request) if hasattr(self, 'process_response'): response = self.process_response(request, response) return response
- 自定义中间件 - 在app文件夹内创建自己的middelware.py中间件创建文件
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse # 必须继承MiddlewareMixin 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请求") #return HttpResponse("Md2中断") def process_response(self,request,response): print("Md2返回") return response ''' process_request、process_response 必须存在类的定义内 当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者。 即,发起请求 - MD1 - MD1的process_request - MD2的process_request - … - 执行视图函数 - … - MD2的process_response - MD1的process_response '''
- 在view内照常定义视图函数
def index(request): print("view函数...") return HttpResponse("OK")
- 在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', 'app01.mymiddelware.MyMiddleware1', 'app01.mymiddelware.MyMiddleware2', ]
2-1 执行结果和过程
正常的执行流程结果:
Md1请求 -- 执行MD1的 process_request Md2请求 -- 执行MD2的 process_request view函数... -- 执行视图函数 Md2返回 -- 执行MD2的 process_response Md1返回 -- 执行MD1的 process_response
注意:如果当请求到达请求2的时候直接不符合条件返回,即return HttpResponse("Md2中断"),程序将把请求直接发给中间件2返回,然后依次返回到请求者
# 返回Md2中断的页面,后台打印如下 Md1请求 Md2请求 Md2返回 Md1返回
流程:
总结:
- 中间件的process_request方法是在执行视图函数之前执行的。
- 当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的索引值,从前到后依次执行的。
- 不同中间件之间传递的request都是同一个对象
多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的,也就是说第一个中间件的process_request方法首先执行,而它的process_response方法最后执行,最后一个中间件的process_request方法最后一个执行,它的process_response方法是最先执行。
三、中间件的常用方法
3-1 process_request、process_response - 请求响应方法
详见 - 二、自定义中间件
3-2 process_view - 调用视图函数前被调用
Django会在调用视图函数之前调用process_view方法。
它应该返回None或一个HttpResponse对象。
如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。
如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。process_view(self, request, view_func, view_args, view_kwargs) ''' 四个参数: request - 是HttpRequest对象。 view_func - 是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。) view_args - 是将传递给视图的位置参数的列表.(无名分组的参数) view_kwargs - 是将传递给视图的关键字参数的字典。(有名分组的参数) 注意:view_args和view_kwargs都不包含第一个视图参数(request)。 '''
3-2-1 process_view 返回为 None 的情况下照常执行
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse 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("Md1view") 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("Md2view") ''' Md1请求 Md2请求 Md1view Md2view view函数... Md2返回 Md1返回 '''
3-2-2 process_view 有返回值, 过其他的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): # return HttpResponse("hello") # 使用 callback 方法调用视图函数 response=callback(request,*callback_args,**callback_kwargs) return response ''' Md1请求 Md2请求 view函数... # 由于process_view内的callback使用 Md2返回 Md1返回 '''
3-3 process_exception - 视图函数中出现异常,执行方法
这个方法只有在视图函数中出现异常了才执行
它返回的值可以是一个None也可以是一个HttpResponse对象。
如果返回HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。
如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。
process_exception(self, request, exception) ''' 该方法两个参数: 一个HttpRequest对象 一个exception是视图函数异常产生的Exception对象。 '''
3-4 process_template_response(self,request,response) - 视图函数的返回值是含有render方法类的对象时,调用方法
# 含有render方法的类 class Test: def __init__(self,status,msg): self.status=status self.msg=msg # render方法 def render(self): import json dic={'status':self.status,'msg':self.msg} return HttpResponse(json.dumps(dic)) # 视图函数 def index(response): # 含有render方法的类Test的对象 return Test(True,'测试')