详解Django中间件的5种自定义方法


Posted in Python onJuly 26, 2018

Django中间件

在http请求 到达视图函数之前 和视图函数return之后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

中间件的执行流程

1、执行完所有的request方法 到达视图函数。

2、执行中间件的其他方法

3、经过所有response方法 返回客户端。

注意:如果在其中1个中间件里 request方法里 return了值,就会执行当前中间件的response方法,返回给用户 然后 报错。。不会再执行下一个中间件。

详解Django中间件的5种自定义方法

自定义中间件

1.在project下随便创建一个py文件

详解Django中间件的5种自定义方法

from django.utils.deprecation import MiddlewareMixin
class Middle1(MiddlewareMixin):
 def process_request(self,request):
  print("来了")
 def process_response(self, request,response):
  print('走了')

2、在setings文件中 注册这个 py文件

django项目的settings模块中,有一个 MIDDLEWARE_CLASSES变量,其中每一个元素就是一个中间件

详解Django中间件的5种自定义方法

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',
 'M1.Middle1',
]

执行结果

详解Django中间件的5种自定义方法

为啥报错了呢?

因为 自定义的中间件response方法没有return,交给下一个中间件,导致http请求中断了!!!

注意自定义的中间件request 方法不要return 因为返回值中间件不再往下执行,导致 http请求到达不了视图层,因为request在视图之前执行!

from django.utils.deprecation import MiddlewareMixin
class Middle1(MiddlewareMixin):
 def process_request(self,request):
  print("来了") #不用return Django内部自动帮我们传递
 def process_response(self, request,response):
  print('走了')
  return response #执行完了这个中间件一定要 传递给下一个中间件

详解Django中间件的5种自定义方法

中间件(类)中5种方法

中间件中可以定义5个方法,分别是:

  • process_request(self,request)
  • process_view(self, request, callback, callback_args, callback_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response

1、 process_view(self, request, callback, callback_args, callback_kwargs)方法介绍

(1)执行完所有中间件的request方法‘

(2)url匹配成功

(3)拿到 视图函数的名称、参数,(注意不执行) 再执行process_view()方法

(4)最后去执行视图函数

玩法1(常规)

from django.utils.deprecation import MiddlewareMixin


class M1(MiddlewareMixin):
 def process_request(self, request):
  print('M1.request') 

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M1.process_view")
  
 def process_response(self, request, response):
  print('M1.response')
  return response 



class M2(MiddlewareMixin):
 def process_request(self, request):
  print('M2.request') 

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M2.process_view")
 
 def process_response(self, request, response):
  print('M2.response')
  return response

执行结果

详解Django中间件的5种自定义方法

玩法2

既然 process_view 拿到视图函数的名称、参数,(不执行) 再执行process_view()方法,最后才去执行视图函数!

那可以在 执行process_view环节直接 把函数执行返回吗?

from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
 def process_request(self, request):
  print('M1.request')
     # callback视图函数名称 callback_args,callback_kwargs 视图函数执行所需的参数
 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M1.process_view")
  response=callback(request,*callback_args,**callback_kwargs)
  return response
 def process_response(self, request, response):
  print('M1.response')
  return response

class M2(MiddlewareMixin):
 def process_request(self, request):
  print('M2.request') 

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M2.process_view")
 def process_response(self, request, response):
  print('M2.response')
  return response

执行结果

详解Django中间件的5种自定义方法

结论:

如果process_view函数有返回值,跳转到最后一个中间件, 执行最后一个中间件的response方法,逐步返回。

和 process_request方法不一样哦! request方法在当前中间件的response方法返回。

2、process_exception(self, request, exception)方法

from django.utils.deprecation import MiddlewareMixin


class M1(MiddlewareMixin):
 def process_request(self, request):
  print('M1.request')
  
 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M1.process_view")

 def process_response(self, request, response):
  print('M1.response')
  return response

 def process_exception(self, request,exception):
  print('M1的process_exception')


class M2(MiddlewareMixin):
 def process_request(self, request):
  print('M2.request') 

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M2.process_view")

 def process_response(self, request, response):
  print('M2.response')
  return response

 def process_exception(self, request, exception):
  print('M2的process_exception')

我去 加了process_exception方法 咋啥也没执行呢?!!原来是process_exception默认不执行!!!

详解Django中间件的5种自定义方法

大爷的 原来process_exception方法在 视图函数执行出错的时候才会执行

M1.request
M2.request
M1.process_view
M2.process_view
执行index
M2的process_exception
M1的process_exception
Internal Server Error: /index/
Traceback (most recent call last):
 File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\exception.py", line 41, in inner
 response = get_response(request)
 File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
 response = self.process_exception_by_middleware(e, request)
 File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
 response = wrapped_callback(request, *callback_args, **callback_kwargs)
 File "F:\untitled1\app01\views.py", line 7, in index
 int("ok")
ValueError: invalid literal for int() with base 10: 'ok'
M2.response
M1.response
[03/Jul/2017 16:43:59] "GET /index/ HTTP/1.1" 500 62663

1、执行完所有 request 方法

2、执行 所有 process_view方法

3、如果视图函数出错,执行process_exception(最终response,process_exception的return值)

如果process_exception 方法有了 返回值 就不再执行 其他中间件的 process_exception,直接执行response方法响应

4.执行所有response方法

5.最后返回process_exception的返回值

M1.request
M2.request
M1.process_view
M2.process_view
执行index
M2的process_exception (有了return值,直接执行response)
M2.response
M1.response

process_exception的应用

在视图函数执行出错时,返回错误信息。这样页面就不会 报错了!

class M1(MiddlewareMixin):
 def process_request(self, request):
  print('M1.request')

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M1.process_view")

 def process_response(self, request, response):
  print('M1.response')
  return response

 def process_exception(self, request,exception):
  print('M1的process_exception')


class M2(MiddlewareMixin):
 def process_request(self, request):
  print('M2.request')

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M2.process_view")

 def process_response(self, request, response):
  print('M2.response')
  return response

 def process_exception(self, request, exception):
  print('M2的process_exception')
  return HttpResponse('出错了兄弟!!!')

3、process_template_response()

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class M1(MiddlewareMixin):
 def process_request(self, request):
  print('M1.request')

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M1.process_view")

 def process_response(self, request, response):
  print('M1.response')
  return response


 def process_exception(self, request,exception):
  print('M1的process_exception')


class M2(MiddlewareMixin):
 def process_request(self, request):
  print('M2.request')

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M2.process_view")

 def process_response(self, request, response):
  print('M2.response')
  return response

 def process_exception(self, request, exception):
  print('M2的process_exception')

 def process_template_response(self,request,response):
  print('M2process_template_response')
  return response

process_template_response()默认不执行

详解Django中间件的5种自定义方法

rocess_template_response()特性

只有在视图函数的返回对象中有render方法才会执行!

并把对象的render方法的返回值返回给用户(注意不返回视图函数的return的结果了,而是返回视图函数 return值(对象)的render方法)

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse


class M1(MiddlewareMixin):
 def process_request(self, request):
  print('M1.request')

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M1.process_view")

 def process_response(self, request, response):
  print('M1.response')
  return response


 def process_exception(self, request,exception):
  print('M1的process_exception')


class M2(MiddlewareMixin):
 def process_request(self, request):
  print('M2.request')

 def process_view(self, request,callback,callback_args,callback_kwargs ):
  print("M2.process_view")

 def process_response(self, request, response):
  print('M2.response')
  return response

 def process_exception(self, request, exception):
  print('M2的process_exception')

 def process_template_response(self,request,response): #如果视图函数中的返回值 中有render方法,才会执行 process_template_response
  print('M2process_template_response')
  return response

视图函数

from django.shortcuts import render,HttpResponse

# Create your views here.
class Foo():
 def __init__(self,requ):
  self.req=requ
 def render(self):
  return HttpResponse('OKKKK')

def index(request):
 print("执行index")
 obj=Foo(request)
 return obj

执行结果

详解Django中间件的5种自定义方法

应用:

既然process_template_respnse,不返回视图函数的return的结果,而是返回视图函数 return值(对象)的render方法;(多加了一个环节)

就可以在 这个视图函数返回对象的 render方法里,做返回值的二次加工了!多加工几个,视图函数就可以随便使用了!

(好比 喷雾器有了多个喷头,换不同的喷头喷出不同水,返回值就可以也组件化了)

from django.shortcuts import render,HttpResponse

# Create your views here.
class Dict(): #对视图函数返回值做二次封装 !!
 def __init__(self,requ,msg):
  self.req=requ 
  self.msg=msg
 def render(self):
  a=self.msg #在render方法里面 把视图函数的 返回值 制作成字典 、列表等。。。 
     # 如果新增了其他 一个视图函数直接,return对象 即可!不用每个视图函数都写 制作字典 列表 拼接的逻辑了
  return HttpResponse(a) #

def index(request):
 print("执行index")
 obj=Dict(request,"vv")
 return obj

中间件应用场景

由于中间件工作在 视图函数执行前、执行后(像不像所有视图函数的装饰器!)适合所有的请求/一部分请求做批量处理

1、做IP限制

放在 中间件类的列表中,阻止某些IP访问了;

2、URL访问过滤

如果用户访问的是login视图(放过)

如果访问其他视图(需要检测是不是有session已经有了放行,没有返回login),这样就省得在 多个视图函数上写装饰器了!

3、缓存(还记得CDN吗?)

客户端请求来了,中间件去缓存看看有没有数据,有直接返回给用户,没有再去逻辑层 执行视图函数

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中self原理实例分析
Apr 30 Python
Python使用一行代码获取上个月是几月
Aug 30 Python
python绘制简单彩虹图
Nov 19 Python
pycharm运行程序时在Python console窗口中运行的方法
Dec 03 Python
实例讲解Python脚本成为Windows中运行的exe文件
Jan 24 Python
Python使用Pandas对csv文件进行数据处理的方法
Aug 01 Python
详解pandas DataFrame的查询方法(loc,iloc,at,iat,ix的用法和区别)
Aug 02 Python
django-rest-swagger对API接口注释的方法
Aug 29 Python
PyCharm下载和安装详细步骤
Dec 17 Python
基于django 的orm中非主键自增的实现方式
May 18 Python
解决python3.x安装numpy成功但import出错的问题
Nov 17 Python
详解python中[-1]、[:-1]、[::-1]、[n::-1]使用方法
Apr 25 Python
python opencv实现切变换 不裁减图片
Jul 26 #Python
Flask之flask-script模块使用
Jul 26 #Python
对tf.reduce_sum tensorflow维度上的操作详解
Jul 26 #Python
TensorFlow用expand_dim()来增加维度的方法
Jul 26 #Python
Python迭代器与生成器基本用法分析
Jul 26 #Python
Python实现矩阵相乘的三种方法小结
Jul 26 #Python
python实现泊松图像融合
Jul 26 #Python
You might like
一个用php3编写的简单计数器
2006/10/09 PHP
php下安装配置fckeditor编辑器的方法
2011/03/02 PHP
js jquery验证银行卡号信息正则学习
2013/01/21 Javascript
js+div实现图片滚动效果代码
2014/02/10 Javascript
7个JS基础知识总结
2014/03/05 Javascript
JavaScript数值数组排序示例分享
2014/05/27 Javascript
JQuery拖动表头边框线调整表格列宽效果代码
2014/09/10 Javascript
js onmousewheel事件多次触发问题解决方法
2014/10/17 Javascript
你不知道的高性能JAVASCRIPT
2016/01/18 Javascript
基于Bootstrap重置输入框内容按钮插件
2016/05/12 Javascript
浅谈Javascript中的12种DOM节点类型
2016/08/19 Javascript
jquery把int类型转换成字符串类型的方法
2016/10/07 Javascript
JS取模、取商及取整运算方法示例
2016/10/13 Javascript
Grunt针对静态文件的压缩,版本控制打包的实例讲解
2017/09/29 Javascript
详解在vue-cli中引用jQuery、bootstrap以及使用sass、less编写css
2017/11/08 jQuery
vue.js实现插入数值与表达式的方法分析
2018/07/06 Javascript
vue+iview分页组件的封装
2020/11/17 Vue.js
JS实现可以用键盘方向键控制的动画
2020/12/11 Javascript
vue实现按钮切换图片
2021/01/20 Vue.js
js动态添加带圆圈序号列表的实例代码
2021/02/18 Javascript
基于JavaScript实现随机点名器
2021/02/25 Javascript
Python时区设置方法与pytz查询时区教程
2013/11/27 Python
Python中实现对list做减法操作介绍
2015/01/09 Python
十条建议帮你提高Python编程效率
2016/02/16 Python
Python安装Numpy和matplotlib的方法(推荐)
2017/11/02 Python
Python中如何导入类示例详解
2019/04/17 Python
HTML5中使用json对象的实例代码
2018/09/10 HTML / CSS
Hotels.com加拿大:领先的在线住宿网站
2018/10/05 全球购物
财务会计专业应届毕业生求职信
2013/10/18 职场文书
干部下基层实施方案
2014/03/14 职场文书
毕业生如何写自荐信
2014/03/26 职场文书
中学生操行评语
2014/04/24 职场文书
关于运动会的广播稿(10篇)
2014/09/12 职场文书
经典祝酒词大全
2015/08/12 职场文书
2020年基层司法所建设情况调研报告
2019/11/30 职场文书
Golang 如何实现函数的任意类型传参
2021/04/29 Golang