详解Python的Django框架中的中间件


Posted in Python onJuly 24, 2015

什么是中间件

我们从一个简单的例子开始。

高流量的站点通常需要将Django部署在负载平衡proxy之后。 这种方式将带来一些复杂性,其一就是每个request中的远程IP地址(request.META["REMOTE_IP"])将指向该负载平衡proxy,而不是发起这个request的实际IP。 负载平衡proxy处理这个问题的方法在特殊的 X-Forwarded-For 中设置实际发起请求的IP。

因此,需要一个小小的中间件来确保运行在proxy之后的站点也能够在 request.META["REMOTE_ADDR"] 中得到正确的IP地址:

class SetRemoteAddrFromForwardedFor(object):
  def process_request(self, request):
    try:
      real_ip = request.META['HTTP_X_FORWARDED_FOR']
    except KeyError:
      pass
    else:
      # HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs.
      # Take just the first one.
      real_ip = real_ip.split(",")[0]
      request.META['REMOTE_ADDR'] = real_ip
(Note: Although the HTTP header is called X-Forwarded-For , Django makes it available as request.META['HTTP_X_FORWARDED_FOR'] . With the exception of content-length and content-type , any HTTP headers in the request are converted to request.META keys by converting all characters to uppercase, replacing any hyphens with underscores and adding an HTTP_ prefix to the name.)

一旦安装了该中间件(参见下一节),每个request中的 X-Forwarded-For 值都会被自动插入到 request.META['REMOTE_ADDR'] 中。这样,Django应用就不需要关心自己是否位于负载平衡proxy之后;简单读取 request.META['REMOTE_ADDR'] 的方式在是否有proxy的情形下都将正常工作。

实际上,为针对这个非常常见的情形,Django已将该中间件内置。 它位于 django.middleware.http 中, 下一节将给出这个中间件相关的更多细节。
安装中间件

要启用一个中间件,只需将其添加到配置模块的 MIDDLEWARE_CLASSES 元组中。 在 MIDDLEWARE_CLASSES 中,中间件组件用字符串表示: 指向中间件类名的完整Python路径。 例如,下面是 django-admin.py startproject 创建的缺省 MIDDLEWARE_CLASSES :

MIDDLEWARE_CLASSES = (
  'django.middleware.common.CommonMiddleware',
  'django.contrib.sessions.middleware.SessionMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
)

Django项目的安装并不强制要求任何中间件,如果你愿意, MIDDLEWARE_CLASSES 可以为空。

这里中间件出现的顺序非常重要。 在request和view的处理阶段,Django按照 MIDDLEWARE_CLASSES 中出现的顺序来应用中间件,而在response和异常处理阶段,Django则按逆序来调用它们。 也就是说,Django将 MIDDLEWARE_CLASSES 视为view函数外层的顺序包装子: 在request阶段按顺序从上到下穿过,而在response则反过来。

Python 相关文章推荐
Python函数学习笔记
Oct 07 Python
Python常见文件操作的函数示例代码
Nov 15 Python
python字典的常用操作方法小结
May 16 Python
Python端口扫描简单程序
Nov 10 Python
Python将字符串常量转化为变量方法总结
Mar 17 Python
解决Django加载静态资源失败的问题
Jul 28 Python
python中通过selenium简单操作及元素定位知识点总结
Sep 10 Python
如何基于Python实现数字类型转换
Feb 07 Python
python随机模块random使用方法详解
Feb 14 Python
利用python对mysql表做全局模糊搜索并分页实例
Jul 12 Python
matplotlib事件处理基础(事件绑定、事件属性)
Feb 03 Python
Python进程池与进程锁之语法学习
Apr 11 Python
浅谈Python的Django框架中的缓存控制
Jul 24 #Python
详解Django缓存处理中Vary头部的使用
Jul 24 #Python
解读Django框架中的低层次缓存API
Jul 24 #Python
Python的Django框架中模板碎片缓存简介
Jul 24 #Python
Django框架下在URLconf中指定视图缓存的方法
Jul 23 #Python
详解Django框架中的视图级缓存
Jul 23 #Python
Django中的CACHE_BACKEND参数和站点级Cache设置
Jul 23 #Python
You might like
php生成缩略图示例代码分享(使用gd库实现)
2014/01/20 PHP
php 发送带附件邮件示例
2014/01/23 PHP
php获取QQ头像并显示的方法
2014/12/23 PHP
php实现refresh刷新页面批量导入数据的方法
2014/12/23 PHP
php中上传文件的的解决方案
2018/09/25 PHP
js获取视频时长代码
2014/04/10 Javascript
Jquery 点击按钮自动高亮实现原理及代码
2014/04/25 Javascript
jQuery统计指定子元素数量的方法
2015/03/17 Javascript
jQuery简单操作cookie的插件实例
2016/01/13 Javascript
AngularJS集合数据遍历显示的实例
2017/12/27 Javascript
vue toggle做一个点击切换class(实例讲解)
2018/03/13 Javascript
详谈js的变量提升以及使用方法
2018/10/06 Javascript
微信小程序wepy框架学习和使用心得详解
2019/05/24 Javascript
vue中获取滚动table的可视页面宽度调整表头与列对齐(每列宽度不都相同)
2019/08/17 Javascript
vue实现全匹配搜索列表内容
2019/09/26 Javascript
vue组件暴露和.js文件暴露接口操作
2020/08/11 Javascript
js面向对象方式实现拖拽效果
2021/03/03 Javascript
[03:02]辉夜杯主赛事第二日 每日之星
2015/12/27 DOTA
python和C语言混合编程实例
2014/06/04 Python
列举Python中吸引人的一些特性
2015/04/09 Python
Python中functools模块的常用函数解析
2016/06/30 Python
深入理解 Python 中的多线程 新手必看
2016/11/20 Python
Python计算指定日期是今年的第几天(三种方法)
2020/03/26 Python
Python爬虫过程解析之多线程获取小米应用商店数据
2020/11/14 Python
使用PyCharm官方中文语言包汉化PyCharm
2020/11/18 Python
小米俄罗斯授权商店:Xiaomi俄罗斯
2019/12/08 全球购物
管事部库房保管员岗位职责
2014/02/21 职场文书
《神奇的克隆》教学反思
2014/04/10 职场文书
项目申报专员岗位职责
2014/07/09 职场文书
优秀共产党员演讲稿
2014/09/04 职场文书
党员干部民主生活会议批评与自我批评材料
2014/09/20 职场文书
工厂门卫岗位职责
2015/04/13 职场文书
考研经验交流会策划书
2015/11/02 职场文书
Python基础之操作MySQL数据库
2021/05/06 Python
详解CSS故障艺术
2021/05/25 HTML / CSS
Python语言中的数据类型-序列
2022/02/24 Python