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 动态获取当前运行的类名和函数名的方法
Apr 15 Python
使用Python判断质数(素数)的简单方法讲解
May 05 Python
Python文件和流(实例讲解)
Sep 12 Python
python处理数据,存进hive表的方法
Jul 04 Python
Python基于递归算法求最小公倍数和最大公约数示例
Jul 27 Python
在Mac下使用python实现简单的目录树展示方法
Nov 01 Python
pandas筛选某列出现编码错误的解决方法
Nov 07 Python
通过python爬虫赚钱的方法
Jan 29 Python
使用Python完成15位18位身份证的互转功能
Nov 06 Python
Python操作Sonqube API获取检测结果并打印过程解析
Nov 27 Python
python GUI库图形界面开发之PyQt5访问系统剪切板QClipboard类详细使用方法与实例
Feb 27 Python
Python中的面向接口编程示例详解
Jan 17 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
PHP脚本的10个技巧(3)
2006/10/09 PHP
php对mongodb的扩展(初出茅庐)
2012/11/11 PHP
PHP简单读取xml文件的方法示例
2017/04/20 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
Js 获取当前日期时间及其它操作实现代码
2021/03/04 Javascript
javascript小数计算出现近似值的解决办法
2010/02/06 Javascript
jquery 简单应用示例总结
2013/08/09 Javascript
IE中JS跳转丢失referrer问题的2个解决方法
2014/07/18 Javascript
浅谈Javascript Base64 加密解密
2014/12/28 Javascript
javascript自动生成包含数字与字符的随机字符串
2015/02/09 Javascript
JS动态修改图片的URL(src)的方法
2015/04/01 Javascript
JQuery包裹DOM节点的方法
2015/06/11 Javascript
第六章之辅组类与响应式工具
2016/04/25 Javascript
Bootstrap学习笔记之js组件(4)
2016/06/12 Javascript
AngularJS入门教程之Scope(作用域)
2016/07/27 Javascript
详解浏览器渲染页面过程
2017/02/09 Javascript
关于预加载InstantClick的问题解决方法
2017/09/12 Javascript
Vue+Vux项目实践完整代码
2017/11/30 Javascript
微信小程序页面传多个参数跳转页面的实现方法
2019/05/17 Javascript
vue 实现动态路由的方法
2020/07/06 Javascript
python中的hashlib和base64加密模块使用实例
2014/09/02 Python
python中lambda函数 list comprehension 和 zip函数使用指南
2014/09/28 Python
Python线程同步的实现代码
2018/10/03 Python
3分钟学会一个Python小技巧
2018/11/23 Python
Pandas之ReIndex重新索引的实现
2019/06/25 Python
Python 字符串、列表、元组的截取与切片操作示例
2019/09/17 Python
django自带的权限管理Permission用法说明
2020/05/13 Python
几款好用的python工具库(小结)
2020/10/20 Python
OpenCV灰度化之后图片为绿色的解决
2020/12/01 Python
Python 利用argparse模块实现脚本命令行参数解析
2020/12/28 Python
利用 Canvas实现绘画一个未闭合的带进度条的圆环
2019/07/26 HTML / CSS
中国汽车租赁行业头部企业:一嗨租车
2019/05/16 全球购物
表演方阵解说词
2014/02/08 职场文书
倡议书格式
2014/04/14 职场文书
中秋节感想
2015/08/10 职场文书
Python写情书? 10行代码展示如何把情书写在她的照片里
2022/04/21 Python