中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量,低级的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件都负责做一些特点的功能.
中间件本质上就是一个类,类中定义了几个方法,Django框架会在处理请求的特定的时间去执行这些方法
settings文件中的MIDDLEWARE配置就是用来存放中间件的
自定义中间件
中间件可以定义五个方法:
-
-
process_view(self, request, view_func, view_args, view_kwargs)
-
process_template_response(self,request,response)
-
process_exception(self, request, exception)
-
process_response(self, request, response)
一般在app文件夹下创建文件夹,在文件夹中的py文件中进行定义
process_request(self,request)
执行时间: 请求到来后,路由匹配之前
执行顺序: 按照注册顺序执行
参数: request --- 项目中所有的request都是同一个
返回值:
None: 正常流程
HttpResponse对象: 直接执行当前中间件的process_response方法,后面中间件中的process_request方法,视图函数都不执行
process_response(self,request,response)
执行时间: 视图函数执行之后
执行顺序: 按照注册顺序倒序执行
参数:
request --- 项目中所有的request都是同一个
response - 返回的响应对象
返回值: HttpResponse 必须返回
process_view(self,request,view_func,view_args,view_kwargs)
执行时间: 路由匹配之后,函数执行之前
执行顺序: 按照注册的顺序执行
参数:
request --- 项目中所有的request都是同一个
view_func --- 视图函数
view_args --- 传给视图的位置参数
view_kwargs --- 传给视图的关键字参数
返回值:
None: 正常流程
HttpReaponse对象: 直接执行最后一个中间件的process_response方法,倒序执行,返回给浏览器,后面中间件的process_view方法,视图都不执行
process_exception(self,request,exception)
执行时间: 视图函数有异常时才执行
执行顺序: 按照注册顺序 倒序执行
参数:
request --- 项目中所有的request都是同一个
exception --- 错误的对象
返回值:
None: 正常流程,交给下一个中间件处理异常,如果每个中间件都返回None,会自动交给django来处理异常(大黄页)
HttpResponse: 直接执行最后一个中间件的process_response方法,倒序执行,返回给浏览器
process_template_response(self,request,response)
执行时间: 视图函数执行之后 要求视图函数返回的对象是TemplateResponse对象 或者是有render方法的HttpResponse对象
执行顺序: 按照注册顺序 倒序执行
参数:
request --- 项目中所有的request都是同一个
response --- 视图函数返回的响应对象
返回值: HttpResponse对象 必须返回
请求流程(生命周期)
登录校验
# url设置 from app01 import views urlpatterns = [ url(r'^login/', views.login), url(r'^index/', views.index), url(r'^home/', views.home), ] # views文件 from django.shortcuts import render, HttpResponse,redirect def login(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') if user == 'alex' and pwd == '123': # 设置session request.session['user'] = user return_url = request.GET.get('return_url') if return_url: return redirect(return_url) else: return redirect('/index/') else: return render(request, 'login.html',{'err_msg':'用户名或密码错误'}) return render(request, 'login.html') def index(request): return HttpResponse('<h1>index</h1>') def home(request): return HttpResponse('<h1>home</h1>') # login.html文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} <div> 用户名 <input type="text" name="user"> </div> <div> 密码 <input type="password" name="pwd"> </div> <div>{{ err_msg }}</div> <button>登录</button> </form> </body> </html> # middleware文件 from django.utils.deprecation import MiddlewareMixin from django.shortcuts import redirect,HttpResponse,render class AuthMD(MiddlewareMixin): white_list = ['/index/','/login/'] def process_request(self,request): return_url = request.path_info # 如果是在白名单内或者登录过的用户,走正常流程,返回None if return_url in self.white_list or request.session.get('user'): return # 否则返回登录页面,将当前页面作为参数写在url里 else: return redirect('/login/?return_url={}'.format(return_url))
import time visit_history = {} class AuthMD2(MiddlewareMixin): def process_request(self, request): # 获取访问ip ip = request.META.get('REMOTE_ADDR') # 获取当前时间 now = time.time() # 获取当前ip之前的访问时间,没有就设置一下 history = visit_history.get(ip,[]) new_list = [] # 存储5秒内的访问时间 for i in history: if now - i < 5: new_list.append(i) if len(new_list) >= 3: return HttpResponse('访问太频繁,请稍后重试') new_list.append(now) visit_history[ip] = new_list