Django中间件
之前的Django电商项目中,使用装饰器实现登陆校验,但是实际上有很多功能是需要所有页面都执行的,比如权限,当不同的用户访问同一个页面,根据权限不同返回的数据也应该不同。首先 可以通过数据库查询限制返回的结果,这样的限制并不能完全对信息进行限制。
在settings当中有这样的一个配置
中间件:是用来处理Django请求的框架级别的钩子,他是一个轻量级的,低级别的插 件系统,用于全局范围改变django的输入与输出。(request,response)
如果django项目存在中间件,用户发起请求,请求首先需要经过 process_request,process_views方法,当视图返回数据的时候,先经过 process_exception,process_template_response,process_response。
上述的五个可以是中间件当中的方法,可以全写,也可以写一部分。
定义:
在项目主目录定义middleware文件,编写中间件类
from django.utils.deprecation import MiddlewareMixin #中间件元类
class MiddlewareTest(MiddlewareMixin):
def process_request(self,request):
"""
:param request: 视图没有处理的请求
"""
print("这是process_request")
def process_view(self,request,view_func,view_args,view_kwargs):
"""
:param request: 视图没有处理的请求
:param view_func: 视图函数
:param view_args: 视图函数的参数,元组格式
:param view_kwargs: 视图函数的参数,字典格式
"""
print("这是process_view")
def process_exception(self,request,exception):
"""
:param request: 视图处理中的请求
:param exception: 错误
"""
print("这是process_exception")
def process_template_response(self,request,response):
"""
:param request: 视图处理完成的请求
:param response: 视图处理完成的响应
"""
print("这是process_template_response")
return response
def process_response(self,request,response):
"""
:param request: 视图处理完成的请求
:param response: 图处理完成的响应
"""
print("这是process_response")
return response
在settings当中进行安装
编写一个视图并请求自动触发中间件
中间件的配置是一个列表,中间件的加载和使用是有顺序的
1、process_request 只有一个参数,是请求,这个请求的request和视图的request是一模 一样的。但是在process_request当中编写代码可以影响到视图当中的request。
from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse
class MiddlewareTest(MiddlewareMixin):
def process_request(self,request):
"""
这里用网站ip黑名单进行演示,在进入视图之前就将其拒绝
"""
black_list = ['aa','bb','abc','user']
user = request.GET.get("user")
if user and user in black_list:
return HttpResponse("404错误")
2、process_view 拥有四个参数
- request 是一个httpRequest对象
- view_func django 即将使用的视图函数
- view_args 视图函数元组参数
- view_kwargs 视图函数的字典参数
无论是view_args还是view_kwargs都不会包含request
对比上述内容:
- process_request 在 process_view之前执行
- process_request只接受request对象,process_view接受request对象和视图函 数及参数
3、process_exception
- request 请求对象
- exception 错误
process_exception方法只有在视图函数当中发生错误才会执行。
def process_exception(self,request,exception):
"""
使用process_exception 记录错误
"""
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
level = "error"
content = str(exception)
log_result = "%s [%s] %s \n"%(now,level,content)
file_path = os.path.join(BASE_DIR,"error.log")
with open(file_path,"a") as f:
f.write(log_result)
print(exception)
自动抛出错误触发process_exception
def test_middleware(request):
print("自定义中间件测试")
raise TypeError("类型错误了,哈哈哈")
return JsonResponse({"name":"测试"})
4、process_template_response
- request 请求对象
- response 响应对象
当前方法只有在视图函数当中返回一个render对象才会执行,通常不会被使用。
当视图函数当中返回有render对象(或者是其他等价的response对象),改方法只会返回render对象返回的内容。
如果被使用,一定要返回一个response对象
视图:
def test_middleware(request):
# def hello():
# return HttpResponse("helloworld")
res = HttpResponse("I am res")
res.render = lambda :HttpResponse("helloworld")
return res
中间件类自定义方法
def process_template_response(self,request,response):
print("I am response")
return response
5、process_response
request 请求对象
response 响应对象
process_response是中间件执行最后的方法,通常用于对响应内容进行再次处理,但是必须返回一个response对象。
def process_response(self,request,response):
"""
中间件执行的最后方法,通常用于对响应内容进行再加工
"""
response.set_cookie("hhh","111")
return response