Django之中间件
一.CBV加装饰器
第一种 @method_decorator(装饰器) 加在get上 第二种 @method_decorator(login_auth,name='get') 加在类上 第三种 @method_decorator(login_auth) 加在dispatch上 3.7版本要return super().dispatch
from django.utils.decorators import method_decorator @method_decorator(login_auth,name='get') #第二种 name参数必须指定 class MyHome(View): @method_decorator(login_auth) #第三种 get和post都会被装饰 def dispatch(self,request,*args,**kwargs): super().dispatch(request,*args,**kwargs) @method_decorator(login_auth) #第一种 def get(self,request): return HttpResponse('get') def post(self,request): return HttpResponse('post')
二.中间件:
1. 首先,什么是中间件?
django请求生命周期完整版,中间件类似于django的门卫,数据在进入和离开时都需要经过中间件
2. 中间件能干嘛?
控制用户访问频率,全局登陆校验,用户访问白名单,黑名单等
3. Django默认有七个中间件,但是django暴露给用户可以自定义中间件并且里面可以写五种方法
中间件可以定义五个方法,分别是:(主要的是process_request和process_response)
有response需要加上return
process_request(self,request)
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)
首先查看settings.py中的七个中间件,然后仿照继承中间件的一个类,从而自定义两个中间件,新创建一个文件夹和文件:
from django.utils.deprecation import MiddlewareMixin class MyMiddleWare(MiddlewareMixin): def process_request(self,request): print('我是第一个自定义的中间件中process_request方法') def process_response(self,request,response): print('我是第一个自定义的中间件中process_response方法') return response class MyMiddleWare1(MiddlewareMixin): def process_request(self,request): print('我是第二个自定义的中间件中process_request方法') def process_response(self,request,response): print('我是第二个自定义的中间件中process_response方法') return response
然后把路径添加在中间件目录的后面:
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', 'mymiddleware.middleware.MyMiddleWare', 'mymiddleware.middleware.MyMiddleWare1' ]
视图函数:
def index(request): print('我是视图函数') return HttpResponse('我是视图函数')
执行顺序:
我是第一个自定义的中间件中process_request方法
我是第二个自定义的中间件中process_request方法
我是视图函数
我是第二个自定义的中间件中process_response方法
我是第一个自定义的中间件中process_response方法
如果process_request返回值是None,程序会继续执行,如果是一个HttpResponse对象(三剑客),程序会在同级掉头,
不会走下一个中间件,更不会走视图函数:
class MyMiddleWare(MiddlewareMixin): def process_request(self,request): print('我是第一个自定义的中间件中process_request方法') return HttpResponse('我是第一个中间件里面返回的对象')
# return render(request, 'index.html') 同理
执行到这个中间件就回头了:
我是第一个自定义的中间件中process_request方法
我是第一个自定义的中间件中process_response方法
process_view方法:路由匹配成功执行视图函数之前会走这个方法
def process_view(self, request, view_func, view_args, view_kwargs): print('我是第一个自定义的中间件中process_view方法') print(view_func.__name__)
执行顺序:
我是第一个自定义的中间件中process_request方法
我是第二个自定义的中间件中process_request方法
我是第一个自定义的中间件中process_view方法
index
我是第二个自定义的中间件中process_view方法
index
我是视图函数
我是第二个自定义的中间件中process_response方法
我是第一个自定义的中间件中process_response方法
process_exception方法:异常捕获,顺序从下往上
def process_exception(self, request, exception): print("我是第一个自定义的中间件中process_exception方法",exception)
process_template_response方法:顺序也是从下往上
def process_template_response(self, request, response):
print('我是第一个自定义的中间件中process_template_response方法')
return response
看效果要用这个视图函数:
def index(request): print("app01 中的 index视图") def render(): print("in index/render") return HttpResponse("O98K") rep = HttpResponse("OK") rep.render = render return rep
流程图:
如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4,5,6中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process_response方法。
假如中间件3 的process_view方法返回了HttpResponse对象,则4,5,6的process_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行。
process_template_response和process_exception两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:
中间件版登陆验证:
urls.py from app02 import views as v2 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/',v2.login), url(r'^home/',v2.home), url(r'^index/',v2.index) ] ---------------------------------------------------------------------------- views.py from django.shortcuts import render,redirect,HttpResponse from app02 import models # Create your views here. def login(request): error_msg='' if request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') user_obj=models.User.objects.filter(username=username,password=password) if user_obj: #设置session request.session['login']='ok' #获取用户想直接访问的URL url=request.GET.get('next') #如果有,就跳转到客户初始想访问的URL if not url: #没有则默认跳转到home页面 url='/home/' return redirect(url) else: error_msg='username or password error!' return render(request,'login.html',{'error_msg':error_msg}) def home(request): return HttpResponse('<h1>这是home页面 只有登录了才能看到</h1>') def index(request): return HttpResponse('<h1>这是index页面 也只有登录了才能看到<h1>') ---------------------------------------------------------------------------- login.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登陆页面</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <form action="" method="post"> {% csrf_token %} <label for="">username:<input type="text" name="username"></label> <label for="">password:<input type="password" name="password"></label> <input type="submit" value="submit"> </form> <h1 style="color: red">{{ error_msg }}</h1> </body> </html> ---------------------------------------------------------------------------- middlewares.py from django.utils.deprecation import MiddlewareMixin from django.shortcuts import redirect class Check_Login(MiddlewareMixin): def process_request(self,request): next_url=request.path_info if not next_url.startswith('/login/'): is_login=request.session.get('login','') if not is_login: return redirect('/login/?next={}'.format(next_url)) ---------------------------------------------------------------------------- 在settings.py中注册 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', 'middleware.my_middleware.Check_Login', ]
Django请求流程图: