Django中间件工作流程及写法实例代码
作者:扎心了老铁 发布时间:2021-09-01 17:47:38
熟悉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
来源:http://www.cnblogs.com/kangoroo/p/7358431.html
猜你喜欢
- asp三天学好ADO对象之第二天 今天来说一下Recordset对象的一些方法。1、AddNew 方法创建可更新 Recordset 对象的
- 如下所示:'''@author: Jacobpc'''import osimport sys
- icech: 在制作网页的时候,常常要遇到制作虚线表格的问题,下面的文章就能解决这个问题。方法一:作一个1X2的图。半黑半白,再利用表格作成
- 学习WEB标准的朋友一般都是从学习CSS开始,为什么呢?因为CSS是一种很有意思的语言,它能让我们的网页千变万化。也许我们一开始的接触只是因
- 前言学习Python的过程中,我们会遇到Excel的各种问题。下面这篇文章主要给大家介绍了关于python对excel进行数据剔除操作的相关
- 本文实例讲述了Python开发的实用计算器。分享给大家供大家参考,具体如下:实现功能:图形界面PyQt,输入框,+,—,*,/ ;乘方 ,开
- 一、项目视图分析通过上图,我们可以看到,一个完整的项目,基本包括三个部分:用户视图层、接口层、数据处理层,其中,用户视图层是用来接收用户的数
- 前言此专栏为python与R语言对比学习的文章;以通俗易懂的小实验,带领大家深入浅出的理解两种语言的基本语法,并用以实际场景!感谢大家的关注
- 实现功能QuestType 1->查询语句, 2->更新语句, 3->删除语句, 4->插入语句<
- 问题描述现有一个有向无权图。如下图所示: 问题:使用某个顶点s作为输入参数,找出从s到所有其他顶点的最短路径。 说明:因为是无权
- 动机: 排序功能让我们页面上的数据显的更人性化,是我们在网站上见过的很普遍的一个功能效果了。以往的自动排序都是用大量的脚本代码来完成的,对一
- 二、XML的定义 XML是一个精简的SGML,它将SGML的丰富功能与HTML的易用性结合到Web的应用中。XML保留了SGML的可扩展功能
- 类的代码: define('QR_MODE_NUL', -1); define('QR_MODE_NUM',
- breakbreak可以用来立即退出循环语句(包括else)continuecontinue可以用来跳过当次循环注意:break和conti
- 1.由于设置了slave的配置信息,mysql在数据库data目录下生成master.info,所以如有要修改相关slave的配置要先删除该
- 我们知道,关系型数据一般以规范化的形式保存,也就是说你应该尽可能少地重复数据;在正常情况下,表与表之间仅通过各种键值实现关联。进一步地讲,规
- 本文实例总结了PHP中非常有用却鲜有人知的函数。分享给大家供大家参考,具体如下:PHP里有非常丰富的内置函数,很多我们都用过,但仍有很多的函
- Oracle是应用最广的大型数据库,而在范式下进行Oracle数据库设计则可以大大减少数据冗余,使数据库维护更方便,可惜范式下的数据表一般不
- php遍历目录和文件的场景在很多时候都能用到,遍历目录方法的方法有好几种,那么应该使用
- 本文实例讲述了python图像处理之反色实现方法。分享给大家供大家参考。具体如下:我们先加载一个8位灰度图像每一个像素对应的灰度值从0-25