django中间件Middleware
熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截。
django中的中间件(middleware)就是类似钩子的一种存在。下面我们来介绍一下,并且给出一些实例。
1、Middleware的工作流程
我盗了一个图,看网上很多人用这个图,来源已经追不明白了。简单声明一下,这个图不是我的。看着图我们分析一下:
1)django的请求相应流程:HttpRequest -> RequestMiddleware -> view function -> ResponseMiddleware -> HttpResponse
可以看到一个请求到响应的过程,中间夹着两个middleware流程,请求中间件和响应中间件。
也就是说,django提供了一种机制,在:
(1)请求到达视图函数中间
(2)视图函数到响应之间
支持嵌入钩子。
这种钩子的特点:
(1)全局,一旦你使用了中间件,并且发布生效的话,所有的请求都会经过你嵌入的中间件。
(2)性能敏感,如果你的中间件性能差的话,那么会影响服务的整体性能。
2) django的middleware包含四个钩子函数:process_request/process_view/process_response/process_exception
process_request:接受request之后确定所执行的view之前
process_view:确定了所要执行的view之后,view真正执行之前
process_response:view执行之后
process_exceptionview:view执行抛出异常
而插入middleware的过程是在settings.py中配置,如下默认配置,我只截取了两个中间件:SessionMiddleware和CommonMiddleware。
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', ...
)
我们简单看一下SessionMiddleware的实现
import time
from importlib import import_module from django.conf import settings
from django.utils.cache import patch_vary_headers
from django.utils.http import cookie_date class SessionMiddleware(object):
def __init__(self):
engine = import_module(settings.SESSION_ENGINE)
self.SessionStore = engine.SessionStore def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
request.session = self.SessionStore(session_key) def process_response(self, request, response):
"""
If request.session was modified, or if the configuration is to save the
session every time, save the changes and set a session cookie or delete
the session cookie if the session has been emptied.
"""
try:
accessed = request.session.accessed
modified = request.session.modified
empty = request.session.is_empty()
except AttributeError:
pass
else:
# First check if we need to delete this cookie.
# The session should be deleted only if the session is entirely empty
if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
response.delete_cookie(settings.SESSION_COOKIE_NAME)
else:
if accessed:
patch_vary_headers(response, ('Cookie',))
if modified or settings.SESSION_SAVE_EVERY_REQUEST:
if request.session.get_expire_at_browser_close():
max_age = None
expires = None
else:
max_age = request.session.get_expiry_age()
expires_time = time.time() + max_age
expires = cookie_date(expires_time)
# Save the session data and refresh the client cookie.
# Skip session save for 500 responses, refs #3881.
if response.status_code != 500:
request.session.save()
response.set_cookie(settings.SESSION_COOKIE_NAME,
request.session.session_key, max_age=max_age,
expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
path=settings.SESSION_COOKIE_PATH,
secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None)
return response
可以看到在SessionMiddleware中默认只实现了process_request和process_response两个hook函数。
我们就以这个例子说明一下一个请求的执行过程。我们假设场景是这样的:
1)从上而下配置了两个Middleware(注意顺序):SessionMiddleware和CommonMiddleware
2)每个Middleware中的四个钩子函数齐全process_request/process_view/process_response/process_exception
执行顺序应该是这样的:
1、HttpRequest
2、SessionMiddleware process_request
3、SessionMiddleware process_view
4、CommonMiddleware process_request
5、CommonMiddleware process_view
6、view
7、CommonMiddleware process_response
8、CommonMiddleware process_exception(如有必要)
9、SessionMiddleware process_response
10、SessionMiddleware process_exception(如有必要)
11、HttpResponse
2、Middleware的写法
Middleware的写法很简单:
1)实现一个类,继承object就行;
2)重写其中的四个钩子函数就可以了。
这里要着重说一个常用的功能。
拦截器/过滤器(filter)
一般来说,每一个请求都要经过process_request这个钩子函数。你的实现中,函数的执行结果必然有两种(你要自己做异常处理):
1)None
2)HttpResponse 对象
如果返回None,请求流程继续执行,也就是继续进入其他的Middleware或者钩子函数。
如果返回HttpResponse对象,那么就直接返回到页面。通过这个功能我们可以做黑名单。
给一个例子:
就是统计pv
# -*- coding:utf-8 -*-
from datetime import datetime
from data_monitor.utils.dbmanager import MysqlManager
from data_monitor.common.constant import MYSQL_JOBS as mysql_config class RequestHookMiddleware(object): def process_request(self, request):
try:
username = request.COOKIES.get('username')
uri = request.path
timestamp = str(datetime.now())
db_obj = MysqlManager(
mysql_config.get('host'),
mysql_config.get('port'),
mysql_config.get('db'),
mysql_config.get('user'),
mysql_config.get('password'),
format=True,
)
field_str = 'username, uri, timestamp'
value_str = '"%s","%s","%s"' % (username, uri, timestamp)
db_obj.insert('pv', field_str, value_str)
db_obj.close()
return
except Exception, ex:
return
django中间件Middleware的更多相关文章
- Django中间件(Middleware)处理请求
关注公众号"轻松学编程"了解更多. 1.面向切面编程 切点(钩子) 切点允许我们动态的在原有逻辑中插入一部分代码 在不修改原有代码的情况下,动态注入一部分代码 默认情况,不中断传播 ...
- 利用Django中间件middleware解决用户未登录问题(转)
add by zhj: Django的中间件一般用于处理通用性的问题,分为五种,按处理顺序为request_middleware,view_middleware,exception_middlewar ...
- Django中间件 (middleware)
中间件是处理django的请求和响应的框架级别的钩子,本质是一个类(直白一点中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作) 由于其影响的是全局,所以需要谨慎使用,使用不当会影响性 ...
- Python菜鸟之路:Django 中间件
前言 在正式说Django中间件之前需要先了解Django一个完整的request的处理流程.我从其他网站扒了几张图过来. 图片一: 文字流程说明:如图所示,一个 HTTP 请求,首先被转化成一个 H ...
- Django中Middleware中间件
Django中Middleware中间件 1 Middleware中间件概述 django中间middleware实质就是一个类,django会根据自己的规则在合适的时机执行中间件相应的方法.实际上当 ...
- Django 详解 中间件Middleware
Django中间件 还是涉及到django的请求生命周期.middle ware 请求穿过中间件到达url,再经过中间件返回给用户. 简单实例 django项目根目录新建一个Middle文件夹,再新建 ...
- django 自定义中间件 middleware
Django 中间件 Django中的中间件是一个轻量级.底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出.中间件的设计为开发者提供了一种无侵入式的开发方式,增强 ...
- Django框架之中间件MiddleWare
Django中的中间件是一个轻量级.底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出.中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健 ...
- day54:django:锁和事务&Ajax&中间件Middleware
目录 1.ORM中的锁和事务 2.Ajax 3.中间件:Middleware 3.1 什么是中间件? 3.2 django请求的生命周期 3.3 中间件可以定义的5个方法 3.4 自定义中间件的流程 ...
随机推荐
- JavaScript 的使用基础总结③
JavaScript 中的对象 JavaScript 中的所有事物都是对象:字符串.数值.数组.函数... JavaScript 允许自定义对象. (一)数组 数组对象的作用是:使用单独的变量名来存储 ...
- 集美大学网络1413第十三次作业成绩(团队八) -- 第二次项目冲刺(Beta阶段)
题目: 团队作业8--第二次项目冲刺(Beta阶段) 团队作业8-成绩: 团队/分值 新加入成员 角色 技术特点 改善的功能. 原因. bug 新增功能. 方法. 如何实现 团队分工改进. 原因 改 ...
- 2015级软工实践k班第一次作业-准备
第一次作业-准备······ 几篇文章阅读下来发现一个事实,还是要有明确的目标,清楚自己需要做什么最为重要.然后根据目标确定需要为之所做的准备工作,考研也好,工作也罢,都是服务于自己的目标. 问题答应 ...
- 测试与发布(Alpha版本)
[Alpha阶段]测试报告 1.测试找出的BUG (1).这种情况刷新就好 (2).文件必须10个才行,多余10个的部分不会进入查重的部分,少于会出错: (3).文件保存在d:\files,由于有些原 ...
- spring在扫描包中的注解类时出现Failed to read candidate component错误
出现:org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate componen ...
- 201521123033《Java程序设计》第7周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 参考资料: XMind answer: 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的co ...
- 201521123111《Java程序设计》第6周学习总结
1. 本章学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...
- 学号:201521123116 《java程序设计》第四周学习总结
1. 本周学习总结 2. 书面作业 Q1. 注释的应用使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看.(截图)答:注释的插入:注释以/开始,以/结束类注释/**.... ...
- update:我的Emacs配置文件
;;设置字体用的 防止中文变成无法识别的框框 (set-default-font "Consolas-11") (set-fontset-font "fontset-d ...
- JAVA课程设计个人博客 学生基本信息管理 201521123117 李心宇
1. 团队课程设计博客链接 http://www.cnblogs.com/ll321/p/7067598.html 2.个人负责模块或任务说明 ①主要有三个界面的设计,包括:登录界面,功能选择界面还有 ...