Django之Middleware中间件方法使用
自定义中间件五个方法(部分方法)实例
自定义中间件项目:
模板Templates
login.html
1 {% load static %} 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <meta charset="UTF-8"> 6 <script src="{% static 'jquery-3.4.1.js' %}"></script> 7 <script src="{% static 'jquery-cookie-1.4.1.js' %}"></script> 8 <title>login</title> 9 </head> 10 <body> 11 <div> 12 用户名:<input type="text" id="username"><br> 13 密码:<input type="password" id="password"><br> 14 {% csrf_token %} 15 <input type="button" id="submit" value="登录"> 16 <span id="warning" style="color: red;"></span> 17 </div> 18 </body> 19 <script> 20 $(function () { 21 $('#submit').click(function () { 22 23 $.ajax({ 24 url:'{% url "login" %}', 25 type:'post', 26 headers:{'X-CSRFToken':$.cookie('csrftoken')}, 27 data:{ 28 username:$('#username').val(), 29 password:$('#password').val(), 30 31 }, 32 success:function (response) { 33 if (response.status){ 34 location.href=response.url 35 }else { 36 $('#warning').text('账号或密码有误!') 37 } 38 } 39 }) 40 }) 41 }) 42 </script> 43 </html>
index.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>index</title> 6 </head> 7 <body> 8 <div> 9 <h1>这是主页index,欢迎您的登录!</h1> 10 <a href="{% url 'logout' %}"></a> 11 </div> 12 </body> 13 </html> 14
控制器urls.py
1 from django.conf.urls import url 2 from django.contrib import admin 3 from app01 import views 4 urlpatterns = [ 5 url(r'^admin/', admin.site.urls), 6 url(r'^login/', views.login,name='login'), 7 url(r'^index/', views.index,name='index'), 8 url(r'^logout/', views.logout,name='logout'), 9 ]
视图views.py
1 from django.shortcuts import render,HttpResponse,redirect 2 from django.urls import reverse 3 import json 4 from django.http import JsonResponse 5 6 # Create your views here. 7 8 def login(request): 9 if request.method=='GET': 10 print('view视图函数') 11 # raise ValueError #视图函数抛出异常时,才会逆序依次执行中自定义中间件中的process_exception方法 12 return render(request,'login.html') 13 elif request.method=='POST': 14 name=request.POST.get('username') 15 psd=request.POST.get('password') 16 if name=='yang' and psd=='123': 17 request.session['status']=True 18 request.session['name']=name 19 20 # return HttpResponse(json.dumps({'status':1,'url':reverse('index')}),content_type='application/json') 21 return JsonResponse({'status':1,'url':reverse('index')}) 22 else: 23 return JsonResponse({'status':0,'url':''}) 24 25 def index(request): 26 return render(request,'index.html') 27 28 def logout(request): 29 request.session.flush()#退出同时清空客户端cookie和服务端session 30 return redirect('login')
自定义中间件middlewares.py
1 #process_request和process_response两个方法最常用 2 3 from django.utils.deprecation import MiddlewareMixin 4 from django.shortcuts import redirect,HttpResponse 5 from django.urls import reverse 6 7 class Middleware1(MiddlewareMixin): 8 def process_request(self, request): 9 print('M1_process_request:wsgi.py封装socket和请求对象request之后,url控制器分发之前') 10 #设置白名单,在url列表中的请求均可不执行该中间件的以下代码,直接绕过登录认证 11 url = [reverse('login'), ]#请求白名单 12 if request.path in url: 13 return None 14 else: 15 if request.session.get('status'): 16 pass 17 else: 18 # 在process_request中,返回值只有为None时才会继续执行后边的中间件,否则直接返回当前process_request中return的内容 19 return redirect('login') 20 def process_view(self, request, view_func, view_args, view_kwargs): 21 print('M1_process_view:控制器映射之后,视图函数执行之前') 22 def process_exception(self, request, exception): 23 print('M1_process_exception:视图函数中捕获到错误时自动触发该函数') 24 def process_response(self,request,response): 25 print('M1_process_response') 26 # 在process_response中,返回值只有为response对象时,才会接力式返回视图函数的返回结果,否则会被process_response中的return结果覆盖,不写则报错 27 return HttpResponse('M1_process_response:视图函数执行之后,wsgi.py封装send之前,返回值不是接力原视图函数resopnse对象,而是被覆盖') 28 # return response 29 30 class Middleware2(MiddlewareMixin): 31 def process_request(self, request): 32 print('M2_process_request:wsgi.py封装socket和请求对象request之后,url控制器分发之前') 33 #在process_request中,返回值只有为None时才会继续执行后边的中间件,否则直接返回当前process_request中return的内容 34 # return HttpResponse('M2_process_request返回不是None直接终止处理返回') 35 def process_view(self, request, view_func, view_args, view_kwargs): 36 print('M2_process_view:控制器映射之后,视图函数执行之前') 37 def process_exception(self, request, exception): 38 print('M2_process_exception:视图函数中捕获到错误时自动触发该函数') 39 def process_response(self,request,response): 40 print('M2_process_response') 41 return HttpResponse('M2_process_response:视图函数执行之后,wsgi.py封装send之前,返回值不是接力原视图函数resopnse对象,而是被覆盖') 42 # return response
配置settings.py
settings.py
执行结果:
后端:
前端:
视图函数抛出异常测试process_exception
中间件补充说明
process_template_response(用的比较少)
process_template_response(self, request, response)
它的参数,一个HttpRequest对象,response是TemplateResponse对象(由视图函数或者中间件产生)。
process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。
1 #中间件: 2 class MD1(MiddlewareMixin): 3 4 def process_request(self, request): 5 print("MD1里面的 process_request") 6 7 def process_response(self, request, response): 8 print("MD1里面的 process_response") 9 return response 10 11 def process_view(self, request, view_func, view_args, view_kwargs): 12 print("-" * 80) 13 print("MD1 中的process_view") 14 print(view_func, view_func.__name__) 15 16 def process_exception(self, request, exception): 17 print(exception) 18 print("MD1 中的process_exception") 19 return HttpResponse(str(exception)) 20 21 def process_template_response(self, request, response): 22 print("MD1 中的process_template_response") 23 return response 24 25 26 class MD2(MiddlewareMixin): 27 def process_request(self, request): 28 print("MD2里面的 process_request") 29 pass 30 31 def process_response(self, request, response): 32 print("MD2里面的 process_response") 33 return response 34 35 def process_view(self, request, view_func, view_args, view_kwargs): 36 print("-" * 80) 37 print("MD2 中的process_view") 38 print(view_func, view_func.__name__) 39 40 def process_exception(self, request, exception): 41 print(exception) 42 print("MD2 中的process_exception") 43 44 def process_template_response(self, request, response): 45 print("MD2 中的process_template_response") 46 return response 47 48 views.py视图: 49 def index(request): 50 print("app01 中的 index视图") 51 #raise ValueError('出错啦') 52 def render(): 53 print("in index/render") 54 #raise ValueError('出错啦') #至于render函数中报错了,那么会先执行process_template_response方法,然后执行process_exception方法,如果是在render方法外面报错了,那么就不会执行这个process_template_response方法了。 55 return HttpResponse("O98K") #返回的将是这个新的对象 56 rep = HttpResponse("OK") 57 rep.render = render 58 return rep 59 60 61 访问index视图,终端输出的结果: 62 MD2里面的 process_request 63 MD1里面的 process_request 64 -------------------------------------------------------------------------------- 65 MD2 中的process_view 66 <function index at 0x000001C111B97488> index 67 -------------------------------------------------------------------------------- 68 MD1 中的process_view 69 <function index at 0x000001C111B97488> index 70 app01 中的 index视图 71 MD2 中的process_template_response 72 MD1 中的process_template_response 73 in index/render 74 MD1里面的 process_response 75 MD2里面的 process_response