Django教程笔记之中间件middleware详解


Posted in Python onAugust 01, 2018

中间件介绍

中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。

每个中间件都会负责一个功能,例如,AuthenticationMiddleware,与sessions处理相关。

激活中间件

需要在settings.py配置文件中,配置MIDDLEWARE_CLASSES:

MIDDLEWARE_CLASSES = [
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

当然你也可以不试用任何的中间件,这个可以设置为空。

中间件顺序

一般我们我们从浏览器发出一个请求 Request,得到一个响应后的内容 HttpResponse ,这个请求传递到 Django的过程如下,process request 和 process response的执行顺序正好相反,如下图所示:

Django教程笔记之中间件middleware详解

也就是说,每一个请求都是先通过中间件中的 process_request 函数,这个函数返回 None 或者 HttpResponse 对象,如果返回前者,继续处理其它中间件,如果返回一个 HttpResponse,就处理中止,返回到网页上。
中间件不用继承自任何类(可以继承 object ),下面一个中间件大概的样子:

class CommonMiddleware(object):
 def process_request(self, request):
 return None

 def process_response(self, request, response):
 return response

需要用到的几个hook:

  • process_request()
  • process_exception() (only if the view raised an exception)
  • process_template_response()
  • process_response()

常用的中间件组件:

1. Sessions

2. Authentication

3. CSRF Protection

4. GZipping Content

例如,比如我们要做一个 流量统计

class BlockedIpMiddleware(object):
 def process_request(self, request):
   ...数据库拿access值
   access = access+1
   ...存起来,类似这个原理

这里的代码的功能就是 简单的访问一次加一次,把这个中间件的 Python 路径写到settings.py中

MIDDLEWARE_CLASSES = (
 'zjj.middleware.BlockedIpMiddleware',
 ...其它的中间件
)

Django 会从 MIDDLEWARE_CLASSES 中按照从上到下的顺序一个个执行中间件中的 process_request 函数,而其中 process_response 函数则是最前面的最后执行。

二,再比如,我们在网站放到服务器上正式运行后,DEBUG改为了 False,这样更安全,但是有时候发生错误不能显示错误详情页面,有没有办法处理好这两个事情呢?

普通访问者看到的是友好的报错信息

管理员看到的是错误详情,以便于修复 BUG

当然可以有,利用中间件就可以做到!代码如下:

import sys
from django.views.debug import technical_500_response
from django.conf import settings

class UserBasedExceptionMiddleware(object):
 def process_exception(self, request, exception):
  if request.user.is_superuser or request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
   return technical_500_response(request, *sys.exc_info())

把这个中间件像上面一样,加到你的 settings.py 中的 MIDDLEWARE_CLASSES 中,可以放到最后,这样可以看到其它中间件的 process_request的错误。

当访问者为管理员时,就给出错误详情,比如访问本站的不存在的页面。

普通人看到的是普通的 404(自己点开看看),而我们却可以看到。

三,分享一个简单的识别手机的中间件,更详细的可以参考这个:django-mobi

MOBILE_USERAGENTS = ("2.0 MMP","240x320","400X240","AvantGo","BlackBerry",
 "Blazer","Cellphone","Danger","DoCoMo","Elaine/3.0","EudoraWeb",
 "Googlebot-Mobile","hiptop","IEMobile","KYOCERA/WX310K","LG/U990",
 "MIDP-2.","MMEF20","MOT-V","NetFront","Newt","Nintendo Wii","Nitro",
 "Nokia","Opera Mini","Palm","PlayStation Portable","portalmmm","Proxinet",
 "ProxiNet","SHARP-TQ-GX10","SHG-i900","Small","SonyEricsson","Symbian OS",
 "SymbianOS","TS21i-10","UP.Browser","UP.Link","webOS","Windows CE",
 "WinWAP","YahooSeeker/M1A1-R2D2","iPhone","iPod","Android",
 "BlackBerry9530","LG-TU915 Obigo","LGE VX","webOS","Nokia5800")

class MobileTemplate(object):
 """
 If a mobile user agent is detected, inspect the default args for the view 
 func, and if a template name is found assume it is the template arg and 
 attempt to load a mobile template based on the original template name.
 """

 def process_view(self, request, view_func, view_args, view_kwargs):
  if any(ua for ua in MOBILE_USERAGENTS if ua in 
   request.META["HTTP_USER_AGENT"]):
   template = view_kwargs.get("template")
   if template is None:
    for default in view_func.func_defaults:
     if str(default).endswith(".html"):
      template = default
   if template is not None:
    template = template.rsplit(".html", 1)[0] + ".mobile.html"
    try:
     get_template(template)
    except TemplateDoesNotExist:
     pass
    else:
     view_kwargs["template"] = template
     return view_func(request, *view_args, **view_kwargs)
  return None

再举一个本地化的中间件的例子:

class LocaleMiddleware(object):

 def process_request(self, request):

  if 'locale' in request.cookies:
   request.locale = request.cookies.locale
  else:
   request.locale = None

 def process_response(self, request, response):

  if getattr(request, 'locale', False):
   response.cookies['locale'] = request.locale

就是将cookies中的locale设置给request中的locale,供给后面使用。

这部分参考了django官方文档以及网络上的一些教程,这里也非常感谢这些前辈的分享。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python的id()函数介绍
Feb 10 Python
Python简单实现阿拉伯数字和罗马数字的互相转换功能示例
Apr 17 Python
python判断设备是否联网的方法
Jun 29 Python
对python sklearn one-hot编码详解
Jul 10 Python
python微元法计算函数曲线长度的方法
Nov 08 Python
基于Python解密仿射密码
Oct 21 Python
Django之choices选项和富文本编辑器的使用详解
Apr 01 Python
keras 获取某层输出 获取复用层的多次输出实例
May 23 Python
在keras里面实现计算f1-score的代码
Jun 15 Python
Django封装交互接口代码
Jul 12 Python
python从ftp获取文件并下载到本地
Dec 05 Python
Python实现将多张图片合成MP4视频并加入背景音乐
Apr 28 Python
flask框架中勾子函数的使用详解
Aug 01 #Python
flask中过滤器的使用详解
Aug 01 #Python
Python拼接微信好友头像大图的实现方法
Aug 01 #Python
Python Flask前后端Ajax交互的方法示例
Jul 31 #Python
Python常见内置高效率函数用法示例
Jul 31 #Python
Python使用jsonpath-rw模块处理Json对象操作示例
Jul 31 #Python
flask-socketio实现WebSocket的方法
Jul 31 #Python
You might like
用Apache反向代理设置对外的WWW和文件服务器
2006/10/09 PHP
php警告Creating default object from empty value 问题的解决方法
2014/04/02 PHP
kohana框架上传文件验证规则写法示例
2014/07/14 PHP
PHP中抽象类,接口功能、定义方法示例
2019/02/26 PHP
javascript十个最常用的自定义函数(中文版)
2009/09/07 Javascript
jquery无缝向上滚动实现代码
2013/03/29 Javascript
jquery 缓存问题的几个解决方法
2013/11/11 Javascript
最常见的左侧分类菜单栏jQuery实现代码
2016/11/28 Javascript
jQuery控制控件文本的长度的操作方法
2016/12/05 Javascript
javascript定时器取消定时器及优化方法
2017/07/08 Javascript
浅谈express 中间件机制及实现原理
2017/08/31 Javascript
JavaScript判断输入是否为数字类型的方法总结
2017/09/28 Javascript
JavaScript实现快速排序的方法分析
2018/01/10 Javascript
基于JS实现带动画效果的流程进度条
2018/06/01 Javascript
node+express框架中连接使用mysql(经验总结)
2018/11/10 Javascript
jQuery+ajax实现批量删除功能完整示例
2019/06/06 jQuery
javascript局部自定义鼠标右键菜单
2020/12/08 Javascript
[01:00:44]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#1COL VS Alliance第三局
2016/03/04 DOTA
Python 元类使用说明
2009/12/18 Python
Python线程创建和终止实例代码
2018/01/20 Python
Python cookbook(数据结构与算法)从序列中移除重复项且保持元素间顺序不变的方法
2018/03/13 Python
Python迭代器与生成器基本用法分析
2018/07/26 Python
Python打开文件,将list、numpy数组内容写入txt文件中的方法
2018/10/26 Python
Python实现银行账户资金交易管理系统
2020/01/03 Python
详解Python3中的 input() 函数
2020/03/18 Python
Scrapy框架介绍之Puppeteer渲染的使用
2020/06/19 Python
HTML5 贪吃蛇游戏实现思路及源代码
2013/09/03 HTML / CSS
美国奢侈品购物平台:Orchard Mile
2018/05/02 全球购物
服务承诺书怎么写
2014/05/24 职场文书
森林防火宣传标语
2014/06/27 职场文书
四风问题对照检查材料
2014/09/22 职场文书
大学军训决心书
2015/02/05 职场文书
我们的节日中秋节活动总结
2015/03/23 职场文书
Vue项目打包、合并及压缩优化网页响应速度
2021/07/07 Vue.js
无线电知识基础入门篇
2022/02/18 无线电
Java详细解析==和equals的区别
2022/04/07 Java/Android