1,还是那句话:写代码的逻辑遵循:简洁,重复性高,可维护性高
1.1>中间件:中间件是一种用来处理Django的请求和响应的框架级别的钩子.它是一个轻量,低级别的插件系统,用于在全局范围内改变Django的输入和输出,每个中间件都负责做一些特定的功能,但有于其影响的是全局,所有需要谨慎使用,使用不当会影响性能,
说的直白一点中间件是帮助我们在视图函数执行之前和执行之后可以做一些额外的操作,它本质上就是一个自定义类,类中定义了几个方法,Django框架会在请求的特定时间去执行这些方法
在settings配置文件:
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', ]
1.2>MIDDLEWARE配置项是一个列表,列表中是一个个字符串,这些字符串其实是一个个类,也就是一个个中间件
1.3>自定义中间件
中间件可以分为5个方法,分别是(主要是process_request和process_response这是Django框架的基本骨架)
1.3.1>process_request(self,request)
1.3.2>process_view(self, view_func, view_args, view_kwargs)
1.3.3>process_template_response(self, request,response)
1.3.4>process_exception(self, request, exception)
1.3.5>process_response(self, request, response)
以上方法的返回值可以是一个None或者是一个HttPresponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户
1.4>settings配置文件的代码
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.my_middlewares.MD1", # 配置文件即使一个 文件中有多个类也要一一去配置 "app01.my_middlewares.MD3", "app02.my_middlewares.MD2", ]
app01下的代码
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse # 写一个注册的类必须继承MiddlewaresMiXin class MD1(MiddlewareMixin): # 请求的中间件的方法 def process_request(self, request): print("这是MD1中的process_request方法") # MD1中间件响应的方法 def process_response(self, request, response): print("这是MD1中的process_response方法") print(response) return response class MD3(MiddlewareMixin): # 同理:这是MD3中请求的方法 def process_request(self, request): print("这是MD3中的process_request方法") # 这是MD3中响应的方法 def process_response(self, request, response): print("这是MD3中的process_response方法") return response
app02的代码
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class MD2(MiddlewareMixin): # 这是MD2的请求方法,可以在这进行一系列操作 def process_request(self, request): print("这是MD2中的process_request方法") # 这是MD2的响应方式,可以在执行完views的视图函数之后再进行一些操作 def process_response(self, request, response): print("这是MD2中process_response方法") print(response) return response
vews函数的代码:
from django.shortcuts import render, HttpResponse # Create your views here. def login(request): print("这是视图函数中的request", request) return HttpResponse("这是app01中的login视图函数"
执行结果:
五种函数的终极代码:
settings中的代码:
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.my_middlewares.MD1", # 注意注册的顺序 "app01.my_middlewares.MD3", "app02.my_middlewares.MD2", ]
app01中的中间件代码
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse # 写一个注册的类必须继承MiddlewaresMiXin class MD1(MiddlewareMixin): # 这是app01中MD1的request方法 def process_request(self, request): print("这是MD1中的process_request方法") # 这是app01中MD1中的response方法 def process_response(self, request, response): print("这是MD1中的process_response方法") # print(response) return response # 这是app01中MD1中的view方法 def process_view(self, request, view_func, view_args, view_kwargs): print("这是MD1中process_view的方法") # 这是app01中MD1中exception方法 def process_exception(self, request, exception): print("这是app01中的MD1中的process_exception方法") # return HttpResponse(str(exception)) # 这是app01中MD1中template_response方法 def process_template_response(self, request, response): print("这是app01中的MD1中的process_template_response方法") return response class MD3(MiddlewareMixin): # 这是app01中MD3中request方法 def process_request(self, request): print("这是MD3中的process_request方法") # 这是app01中MD3中response的方法 def process_response(self, request, response): print("这是MD3中的process_response方法") return response # 这是app01中MD3的view方法 def process_view(self, request, view_func, view_args, view_kwargs): print("这是MD3中的process_view方法") # 这是app01中MD3中的exception方法 def process_exception(self, request, exception): print("这是app01中的MD3的process_exception方法") # return HttpResponse(str(exception)) # 这是app01中MD3中的方法 def process_template_response(self, request, response): print("这是app01中MD3的方法process_template_response方法") return response
app02中间件的代码
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse, redirect class MD2(MiddlewareMixin): # 这是MD2的请求方法,可以在这进行一系列操作 def process_request(self, request): print("这是MD2中的process_request方法") # 这是MD2的响应方式,可以在执行完views的视图函数之后再进行一些操作 def process_response(self, request, response): print("这是MD2中process_response方法") print(request) print(response) return response # 这是app02中的MD2中的xiew方法 def process_view(self, request, view_func, view_args, view_kwargs): print("这是app2中MD2中process_view的方法") def login_request(fn): def inner(request, *args, **kwargs): # 判断在跳转页面的时候cookies设置的值 if not request.COOKIES.get("is_login") == "miss": # 如果cookies的键值对不成立则要先返回登录页面,登陆成功以后,再返回用户之前要登录的页面 # 先获取到用户开始想要登录的页面路径 path = request.path_info return redirect("/login/?path={}".format(path)) # 先跳转login页面,再跳转到原来要登录的页面 ret = fn(request, *args, **kwargs) return ret return inner # 这是app02中MD2中的exception方法 def process_exception(self, request, exception): print("这是app02中的MD2的process_exception方法") return HttpResponse(str(exception)) # 这是app02中MD2的template_response方法 def process_template_response(self, request, response): print("这是pp02中的MD2中的process_template_response") print(response) return response
view视图函数的代码:
# def login(request): # print("这是视图函数中的request", request) # xue_xue = 10 # # for i in xue_xue: # # print(i) # return HttpResponse("这是app01中的login视图函数") # # # def index(request): # print("这是视图函数中的index") # ret = HttpResponse("o98k") # # def xue_xue(): # print("这是视图函数index中的xue_xue函数") # # print(response) # return HttpResponse("真几把烦?") # ret.render = xue_xue # 必须把xue_xue这个函数赋值给ret.render,还必须是render # print("这是xue_xue内存函数的地址:",xue_xue) # print("这是视图函数中ret.render:", ret.render) # print("这是index函数的存地址:", index) # print(ret) # # return ret
执行代码:
小结:在视图函数之前执行的中间件函数有:process_resquest, process_exception. process_view,在视图函数之后执行的中间函数有:process_template_response, process_response.
(1)process_request:执行时间 --->在视图函数执行之前,
参数:request --->视图函数中用到的request,
执行顺序: --->按照注册顺序执行
返回值: --->None 正常流程走,
HttpResponse对象当中间件后面的中间件的process_request和process_response方法,视图函数都不执行,执行当前中间的process_response方法和以及之前的中间的process_response方法
(2)process_response:执行时间: --->在视图函数执行之后
参数: --->request,视图函数中用到request,response --->视图函数中返回的response
返回值: --->必须是response对象
执行顺序: --->按照注册顺序倒序执行
(3)process_view: 执行时间 --->在process_request之后, 路由匹配之后,视图函数之前
参数: --->view_func ---->>要执行的视图函数
view_args --->>视图函数的位置参数
view_kwargs --->视图函数中的关键字参数
返回值: --->None 正常走
执行顺序: --->按照注册顺序执行
(4)process_exception(self, request, exception):
执行时间(触发条件:有异常才执行) --->在视图函数之后,在process_response之前
参数:exception --->错误信息对象
返回值: --->None 正常走
--->HttpResponse对象,注册顺序之前的中间件的process_exception方法不走了,执行所有中间件的process_response方法
执行顺序: 按照注册顺序倒序执行
(5)process_template_response(self, request, response):
执行时间: --->(触发条件:reponse对象要有一个render方法),在视图函数之后, 在process_response之前
参数:无
返回值: --->返回respose
执行顺序: --->按照注册顺序倒序执行
Django框架请求的生命周期:
中间件的执行流程:
请求件到达中间件以后,先按照正常顺序执行每个注册的重点件process_request方法,process_request方法返回的值是None,就依次执行,如果返回的值是HttpResponse对象,不在执行后面的process_request方法,而是执行当前对应中间件的process_response方法,将HttpResponse对象返回给浏览器,也就是说:如果MIDDLEWEAR中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,name第4,5,6中间件process_request和process_response都不执行,顺序执行3,2,1中间件ed方法.
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两个方法的触发是有条件的,执行顺序也是倒序,所有流程如下:
AuthMD中间件注册后,所有的请求都要走AuthMD的process_request方法.访问的URL在白名单或者session中有user用户名,则不做阻拦走正常流程;如果URL在黑名单中,则返回This is an illegal URL的字符串;正常URL但是需要登录后访问,让浏览器转到登录页面.注:AuthMD中间件需要session, 所以AuthMD注册的位置要在session中间的下方
附Django请求流程图: