Django之中间件7个保安
Django请求生命周期流程图
什么是中间件?
官方表达:中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。
大白话:中间件就是默认的7个保安,数据来了由外向内一层一层过,数据走了由内向外一层一层过。当某一层不通过就返回报错信息。
7个保安?
# django中间件
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中间件来帮你完成
全局用户身份校验
全局用户访问频率校验
用户访问黑名单
用户访问白名单
自定义中间件
中间件可以定义的五个方法?
必须掌握的:
1. process_request(self,request) ******(掌握)
2.process_response(self, request, response) (掌握)
需要了解的:
3.process_view(self, request, view_func, view_args, view_kwargs)
4.process_template_response(self,request,response)
5.process_exception(self, request, exception)
class Mymd1(MiddlewareMixin):
def process_request(self,request):
print('我是第一个自定义中间件里面的process_request方法')
# return HttpResponse("我是第一个中间件返回的Httpresponse对象")
def process_response(self,request,response):
print('我是第一个中间件里面的process_reponse方法')
return response # 就是后端返回给前端浏览器的响应数据
def process_view(self,request,view_func,*args,**kwargs):
print(view_func,args,kwargs)
print('我是第一个中间件里面的process_view')
def process_template_response(self,request,response):
print('我是第一个中间件里面的process_template_reponse方法')
return response
def process_exception(self,request,exception):
print('exception:',exception)
print('我是第一个中间件里面的process_exception')
class Mymd2(MiddlewareMixin):
def process_request(self,request):
print('我是第二个自定义中间件里面的process_request方法')
def process_response(self, request, response):
print('我是第二个中间件里面的process_reponse方法')
return response
def process_view(self,request,view_func,*args,**kwargs):
print(view_func,args,kwargs)
print('我是第二个中间件里面的process_view')
def process_template_response(self,request,response):
print('我是第二个中间件里面的process_template_reponse方法')
return response
def process_exception(self,request,exception):
print('exception:',exception)
print('我是第二个中间件里面的process_exception')
注册:
1.process_request(self,request)
一次执行每一个中间键的request方法,一旦返回了HttpResponse对象,则请求不再继续往后执行,而是直接跳到同级别的process_request的方法
process_request(self,request) 在执行视图函数之前执行
请求来的时候会按照配置文件中注册的中间件从上往下的顺序依次执行每一个中间件里面的process_request方法,如果没有直接跳过执行下一个
2.process_response
process_response
视图函数之后执行,此时过安检由内向外,后注册的先运行。
process_response方法 该方法必须要有两个形参 并且需要将形参response返回,response就是返回给浏览器的内容
如果你内部自己返回了HttpResponse对象 会将返回给用户浏览器的内容替换成你自己的
def process_response(self,request,response):
print('我是第一个中间件里面的process_reponse方法')
return response # 就是后端返回给前端浏览器的响应数据
3.process_view
process_view
路由系统之后,视图系统之前执行
process_view(self, request, view_func, view_args, view_kwargs)
该方法有四个参数:
request是HttpRequest对象。
view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)
view_args是将传递给视图的位置参数的列表.
view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。
Django会在调用视图函数之前调用process_view方法。
它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,那么将不会执行Django的视图函数,而是直接在中间件中掉头,倒叙执行一个个process_response方法,最后返回给浏览器
4.process_exception
process_exception
当视图函数报错的时候自动触发
process_exception(self, request, exception)
该方法两个参数:
一个HttpRequest对象
一个exception是视图函数异常产生的Exception对象。
这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。
5.process_template_reponse
process_template_reponse(用的比较少)
视图函数执行完成后立即执行
process_template_response(self, request, response)
它的参数,一个HttpRequest对象,response是TemplateResponse对象(由视图函数或者中间件产生)。
process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。
中间件执行的流程
上一部分,我们了解了中间件中的5个方法,它们的参数、返回值以及什么时候执行,现在总结一下中间件的执行流程。
请求到达中间件之后,先按照正序执行每个注册中间件的process_request方法,process_request方法返回的值是None,就依次执行,如果返回的值是HttpResponse对象,不再执行后面的process_request方法,而是执行当前对应中间件的process_response方法(注意不是掉头执行所有的process_response方法),将HttpResponse对象返回给浏览器。也就是说:如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4,5,6中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process_response方法。
process_request方法都执行完后,匹配路由,找到要执行的视图函数,先不执行视图函数,先执行中间件中的process_view方法,process_view方法返回None,继续按顺序执行,所有process_view方法执行完后执行视图函数。假如中间件3 的process_view方法返回了HttpResponse对象,则4,5,6的process_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行。
process_template_response和process_exception两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下: