熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截。
django中的中间件(middleware)就是类似钩子的一种存在。下面我们来介绍一下,并且给出一些实例。
1、Middleware的工作流程
我盗了一个图,看网上很多人用这个图,来源已经追不明白了。简单声明一下,这个图不是我的。看着图我们分析一下:
1)django的请求相应流程:HttpRequest -> RequestMiddleware -> view function -> ResponseMiddleware -> HttpResponse
可以看到一个请求到响应的过程,中间夹着两个middleware流程,请求中间件和响应中间件。
也就是说,django提供了一种机制,在:
- 请求到达视图函数中间
- 视图函数到响应之间
支持嵌入钩子。
这种钩子的特点:
- 全局,一旦你使用了中间件,并且发布生效的话,所有的请求都会经过你嵌入的中间件。
- 性能敏感,如果你的中间件性能差的话,那么会影响服务的整体性能。
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中间件工作流程及写法实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新日志
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]