详解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登录并获取CSDN博客所有文章列表代码实例
Dec 28 Python
Python日志模块logging基本用法分析
Aug 23 Python
python实现机器学习之多元线性回归
Sep 06 Python
Python3 读、写Excel文件的操作方法
Oct 20 Python
Python使用paramiko操作linux的方法讲解
Feb 25 Python
django 自定义过滤器(filter)处理较为复杂的变量方法
Aug 12 Python
tensorflow:指定gpu 限制使用量百分比,设置最小使用量的实现
Feb 06 Python
pandas中的数据去重处理的实现方法
Feb 10 Python
windows10环境下用anaconda和VScode配置的图文教程
Mar 30 Python
Python中相见恨晚的技巧
Apr 13 Python
Python中的min及返回最小值索引的操作
May 10 Python
Python matplotlib安装以及实现简单曲线的绘制
Apr 26 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
PHP中调用ASP.NET的WebService的代码
2011/04/22 PHP
php开发文档 会员收费1期
2012/08/14 PHP
php使用cookie实现记住用户名和密码实现代码
2015/04/27 PHP
PHP设计模式之模板方法模式实例浅析
2018/12/20 PHP
thinkphp5框架扩展redis类方法示例
2019/05/06 PHP
JS效率个人经验谈(8-15更新),加入range技巧
2007/01/09 Javascript
Save a File Using a File Save Dialog Box
2007/06/18 Javascript
JavaScript判断IE版本型号
2015/07/27 Javascript
详解JavaScript操作HTML DOM的基本方式
2015/10/21 Javascript
javascript跨域的方法汇总
2015/10/23 Javascript
JavaScript位移运算符(无符号) >>> 三个大于号 的使用方法详解
2016/03/31 Javascript
getElementById().innerHTML与getElementById().value的区别
2016/10/27 Javascript
vue mintui-Loadmore结合实现下拉刷新和上拉加载示例
2017/10/12 Javascript
echarts鼠标覆盖高亮显示节点及关系名称详解
2018/03/17 Javascript
vue鼠标移入添加class样式,鼠标移出去除样式(active)实现方法
2018/08/22 Javascript
vue展示dicom文件医疗系统的实现代码
2018/08/27 Javascript
CentOS7中源码编译安装NodeJS的完整步骤
2018/10/13 NodeJs
vue element table中自定义一些input的验证操作
2020/07/18 Javascript
python学习手册中的python多态示例代码
2014/01/21 Python
Python2.7 实现引入自己写的类方法
2018/04/29 Python
使用Python开发SQLite代理服务器的方法
2018/12/07 Python
python读取xlsx的方法
2018/12/25 Python
python 搭建简单的http server,可直接post文件的实例
2019/01/03 Python
使用Python实现跳帧截取视频帧
2019/05/31 Python
python 在某.py文件中调用其他.py内的函数的方法
2019/06/25 Python
廉价连衣裙和婚纱礼服在线销售:Tbdress
2019/02/28 全球购物
索尼巴西商店:Sony巴西
2019/06/21 全球购物
土木工程应届生自荐信
2013/09/24 职场文书
大型会议接待方案
2014/03/01 职场文书
会计岗位职责模板
2014/03/12 职场文书
英文升职感谢信
2015/01/23 职场文书
事业单位财务人员岗位职责
2015/04/14 职场文书
2015年中职班主任工作总结
2015/05/25 职场文书
MySQL的Query Cache图文详解
2021/07/01 MySQL
MySQL数据库如何给表设置约束详解
2022/03/13 MySQL
Docker容器harbor私有仓库部署和管理
2022/08/05 Servers