Django—中间件

CBV加装饰器(session)

要在CBV视图中使用我们上面的check_login装饰器,有以下三种方式:

from django.utils.decorators import method_decorator

1from django.shortcuts import render,redirect,HttpResponse 2from django.views import View 3from django.utils.decorators import method_decorator 4 5# Create your views here. 6def login(request): 7 if request.method == 'POST': 8 username = request.POST.get('username') 9 password = request.POST.get('password') 10 if username == 'zyl' and password == '123': 11 request.session['name'] = 'zyl' 12 return redirect('/home/') 13 return render(request,'login.html') 14 15from functools import wraps 16def login_auth(func): 17 @wraps(func) 18 def inner(request,*args,**kwargs): 19 if request.session.get('name'): 20 return func(request,*args,**kwargs) 21 return redirect('/login/') 22 return inner 23 24# @method_decorator(login_auth,name='get') 第二种 name参数必须指定 25class MyHome(View): 26 @method_decorator(login_auth) # 第三种 get和post都会被装饰 27 def dispatch(self, request, *args, **kwargs): 28 super().dispatch(request,*args,**kwargs) 29 # @method_decorator(login_auth) # 第一种 30 def get(self,request): 31 return HttpResponse('get') 32 def post(self,request): 33 return HttpResponse('post')

urls.py

1url(r'^login/', views.login), 2url(r'^home/', views.MyHome.as_view()),

中间件

当Django处理一个Request的过程是首先通过中间件,然后再通过默认的URL方式进行的。我们可以在Middleware这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Response,
主要用于在全局范围内改变Django的输入和输出

中间件能干嘛?

控制用户访问频率,全局登录校验,用户访问白名单,黑名单等

Django默认的Middleware如下:

1MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware', 3 'django.contrib.sessions.middleware.SessionMiddleware', 4 'django.middleware.common.CommonMiddleware', 5 'django.middleware.csrf.CsrfViewMiddleware', 6 'django.contrib.auth.middleware.AuthenticationMiddleware', 7 'django.contrib.messages.middleware.MessageMiddleware', 8 'django.middleware.clickjacking.XFrameOptionsMiddleware', 9]

每一个中间件都有具体的功能。中间件可以定义五个方法。

1.请求来的时候会依次执行每一个中间件里面的process_request方法(如果没有直接通过)
2.响应走的时候会依次执行每一个中间件里面的process_response方法(如果没有直接通过)

分析源码

from django.middleware.security import SecurityMiddleware

 同样,我们再查看一个:

from django.middleware.common import CommonMiddleware

再来

from django.middleware.csrf import CsrfViewMiddleware

我们会发现一个相同点,就是都有process_request和process_response,但并不是所有的中间件都有process_request,但是所有的中间件都是由process_response,而且process_response必须要有返回值,process_request没有,如果process_request有返回值的话就不会执行后面的程序了(所以这里可以拦截)

我们从浏览器发出一个请求Request,得到一个响应后的内容HttpResponse,也就是说,每一个请求都是先通过中间件中的process_request函数,这个函数返回None 或者HttpResponse 对象,如果返回前者,继续处理其他中间件,如果返回前者,继续处理其他中间件,如果返回一个HttpResponse,就处理终止,返回到网页上。

中间件不用集成任何类(可以继承object),下面一个中间件大概的样子:

1class CommonMiddleware(object): 2 def process_request(self, request): 3 return None 4 5 def process_response(self, request, response): 6 return response

自定义中间件的方法

中间件一共有五个方法:

1process_request(self, request) 2 3process_view(self, request, callback, callback_args, callback_kwargs) 4 5process_template_response() 6 7process_exception(self, request, exception) 8 9process_response(self, request, response)

Request预处理函数:process_request(self,request)

  如果返回None,Django继续执行这个request,如果返回的是HttpRsoponse对象,Django不会执行任何除了process_response以外的其他中间件以及相应的view,Django立即返回该HttpResponse

View预处理函数:process_view(self, request, callback, callback_args, callback_kwargs)

  这个方法的条用实际在Django执行完request预处理函数并确定待执行的view之后,但在view函数实际执行之前

1request:HttpRequest 对象。 2 3callback:Django将调用的处理request的python函数. 这是实际的函数对象本身, 4 而不是字符串表述的函数名。 5 6args:将传入view的位置参数列表,但不包括request参数(它通常是传入view的第一个参数)7 8kwargs:将传入view的关键字参数字典。

process_view() 应当返回None或 HttpResponse 对象。如果返回 None, Django将继续处理这个request ,执行后续的中间件, 然后调用相应的view。

如果返回 HttpResponse 对象,Django 将不再执行任何其它的中间件(不论种类)以及相应的view,Django将立即返回。

Template模板渲染函数:process_template_response()

  默认不执行,只有在视图函数的返回结果对象中有render方法才会执行,并把对象的render方法的返回值返回给用户(注意不返回视图函数的return的结果了,而是返回视图函数return值(对象)中render方法的结果)

Exception后处理函数:process_exception(self, request, exception)

这个方法只有在request处理过程中出了问题并且view函数抛出了一个未捕获的异常才会被调用。这个钩子可以用来发送错误通知,将现场相关信息输出到日志文件,或者甚至尝试从错误中自动恢复。

Response 后处理函数:process_response(self, request, response)

这个方法的调用时机在 Django 执行 view 函数并生成 response 之后。

1总结: 2 需要你掌握的: 3 process_request:请求来的时候从上往下依次执行每一个中间件里面的process_request 4 process_response :响应走的时候会从下往上依次执行每一个中间件里面的process_response方法 5 6 了解: 7 process_view:路由匹配成功执行视图之前自动触发(从上往下依次执行) 8 process_exception:当视图函数报错了,自动触发(从下往上依次执行) 9 process_template_response:视图函数返回的对象有一个render()方法 10 (或者表明该对象是一个TemplateResponse对象或等价方法)(从下往上依次执行) 11

自定义中间件方法练习

process_request 和 process_response方法

当用户发起请求的时候会依次经过所有的中间件,这个时候的请求是process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者。

  上述截图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin。

需要导入:

from django.utils.deprecation import MiddlewareMixin

在 views 中:

1def index(request): 2 3 print("view函数...") 4 return HttpResponse("OK")

1from django.utils.deprecation import MiddlewareMixin 2from django.shortcuts import HttpResponse 3 4class Md1(MiddlewareMixin): 5 def process_request(self,request): 6 print('md1请求') 7 8 def process_response(self,request,response): 9 print('md1返回') 10 return response 11 12class Md2(MiddlewareMixin): 13 def process_request(self,request): 14 print('md2请求') 15 16 def process_response(self,request,response): 17 print('md2返回') 18 return response

 

1 1 from django.utils.deprecation import MiddlewareMixin 2 2 from django.shortcuts import HttpResponse 3 3 4 4 class Md1(MiddlewareMixin): 5 5 def process_request(self,request): 6 6 print('md1请求') 7 7 8 8 def process_response(self,request,response): 9 9 print('md1返回') 1010 return response 1111 1212 class Md2(MiddlewareMixin): 1313 def process_request(self,request): 1414 print('md2请求') 1515 return HttpResponse('M2中断d') 1616 def process_response(self,request,response): 1717 print('md2返回') 1818 return response

注意:如果当请求到达请求2的时候直接不符合条件返回,即return HTTPResponse(“Md2中断”),程序将请求直接发给中间件2 返回,然后依次返回到请求者

流程图

process_view 方法

1from django.utils.deprecation import MiddlewareMixin 2from django.shortcuts import HttpResponse 3 4class Md1(MiddlewareMixin): 5 def process_request(self,request): 6 print('md1请求') 7 8 def process_response(self,request,response): 9 print('md1返回') 10 return response 11 12 def process_view(self,request,callback, callback_args, callback_kwargs): 13 print('Md1view') 14 15class Md2(MiddlewareMixin): 16 def process_request(self,request): 17 print('md2请求') 18 # return HttpResponse('M2中断d') 19 def process_response(self,request,response): 20 print('md2返回') 21 return response

结果

流程图

CSRF跨站请求伪造

  我们之前已经接触过一个csrf相关的中间件了?我们一开始让大家把他注释掉,再提交post请求的时候,就不会被forbidden了,后来学会使用csrf_token之后就不再注释这个中间件了。

简介

django为用户实现防止跨站请求伪造的功能,通过中间件

django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

 方式

1$.ajaxSetup({ 2 data: {csrfmiddlewaretoken: '{{ csrf_token }}' }, 3}); 4 5<form action="/index3/" method="post"> 6{# {% csrf_token %}#} 7 <p>username:<input type="text" name="username"></p> 8 <p>money:<input type="text" name="money"></p> 9 <p>others:<input type="text" name="others"></p> 10 <input type="submit"> 11</form> 12<button>ajax</button> 13<script> 14 $('button').click(function () { 15 $.ajax({ 16 url:'', 17 type:'post', 18 data:{'name':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()}, 19 success:function (data) { 20 console.log(data) 21 } 22 }) 23 }) 24</script> 25 26from django.views.decorators.csrf import csrf_exempt,csrf_protect 27@csrf_exempt # 不校验csrf 28def index1(request): 29 return HttpResponse('ok') 30 31@csrf_protect # 校验csrf 32def index2(request): 33 return HttpResponse('ok')

csrf装饰CBV

1from django.utils.decorators import method_decorator 2 3# @method_decorator(csrf_exempt,name='post') # 不行 不能给单独某一个视图函数加 4@method_decorator(csrf_exempt,name='dispatch') # 可以 5class Index3(View): 6 # @method_decorator(csrf_exempt) # 第三种 可以 7 def dispatch(self, request, *args, **kwargs): 8 super().dispatch(request,*args,**kwargs) 9 10 def get(self,request): 11 return HttpResponse('get') 12 13 # @method_decorator(csrf_exempt) # 不行 14 def post(self,request): 15 return HttpResponse('post')

csrf装饰CBV需要注意(******)
csrf_protect 跟正常的CBV装饰器一样 三种
csrf_exempt 只能有下面两种方式
@method_decorator(csrf_exempt,name='dispatch') # 第一种
class Index3(View):
# @method_decorator(csrf_exempt) # 第二种
def dispatch(self, request, *args, **kwargs):
super().dispatch(request,*args,**kwargs)
其实都是给dispatch加

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )