Flask 扩展 缓存
如果同一个请求会被多次调用,每次调用都会消耗很多资源,并且每次返回的内容都相同,就该使用缓存了
自定义缓存装饰器
在使用Flask-Cache扩展实现缓存功能之前,我们先来自己写个视图缓存装饰器,方便我们来理解视图缓存的实现。首先,我们要有一个缓存,Werkzeug框架中的提供了一个简单的缓存对象SimpleCache,它是将缓存项存放在Python解释器的内存中,我们可以用下面的代码获取SimpleCache的缓存对象:
from werkzeug.contrib.cache import SimpleCache
cache = SimpleCache()
如果你要使用第三方的缓存服务器,比如Memcached,Werkzeug框架也提供了它的wrapper:
from werkzeug.contrib.cache import MemcachedCache
cache = MemcachedCache(['127.0.0.1:11211'])
此后就可以使用cache对象的”set(key, value, timeout)”和”get(key)”方法来存取缓存项了。注意”set()”方法的第三个参数”timeout”是缓存过期时间,默认为0,也就是永不过期。
def cached(timeout=5 * 60, key='view_%s'):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = key % request.path
value = cache.get(cache_key)
if value is None:
value = f(*args, **kwargs)
cache.set(cache_key, value, timeout=timeout)
return value
return decorated_function
return decorator
装饰器的两个参数分别是缓存的过期时间,默认是5分钟;缓存项键值的前缀,默认是”view_”。然后我们写个视图,并使用此装饰器:
@app.route('/hello')
@app.route('/hello/<name>')
@cached()
def hello(name=None):
    print 'view hello called'
    return render_template('hello.html', name=name)
我们试下访问这个视图,对于同样的URL地址,第一次访问时,控制台上会有”view called”输出,第二次就不会了。如果过5分钟后访问,”view called”才会再次输出。
安装和启用Flask-Cache
了解了缓存装饰器的内部实现,我们就可以开始介绍Flask的缓存扩展,Flask-Cache。首先使用pip将其安装上:
pip install flask-cache
然后创建一个Flask-Cache的实例:
from flask import Flask
from flask_cache import Cache app = Flask(__name__)
cache = Cache(app, config={'CACHE_TYPE': 'simple'})
上例中,我们使用了’simple’类型缓存,其内部实现就是Werkzeug中的SimpleCache。我们也可以使用第三方的缓存服务器,比如Redis,代码如下:
cache = Cache(app, config={'CACHE_TYPE': 'redis',          # Use Redis
                           'CACHE_REDIS_HOST': 'abc.com',  # Host, default 'localhost'
                           'CACHE_REDIS_PORT': 6379,       # Port, default 6379
                           'CACHE_REDIS_PASSWORD': '',  # Password
                           'CACHE_REDIS_DB': 2}            # DB, default 0
其内部实现是”werkzeug.contrib.cache”包下的”RedisCache”,所以说Flask-Cache就是基于Werkzeug框架的Cache库实现的。
应用中使用缓存
同自定义缓存装饰器一样,我们可以用cache对象的”cached()”方法来装饰视图函数,以达到缓存视图的目的:
@app.route('/hello')
@app.route('/hello/<name>')
@cache.cached(timeout=300, key_prefix='view_%s', unless=None)
def hello(name=None):
    print 'view hello called'
    return render_template('hello.html', name=name)
“cache.cached()”装饰器有三个参数:
- timeout:过期时间,默认为None,即永不过期
- key_prefix:缓存项键值的前缀,默认为”view/%s”
- unless:回调函数,当其返回True时,缓存不起作用。默认为None,即缓存有效
除了装饰视图函数,”cache.cached()”装饰器也可以用来装饰普通函数:
@cache.cached(timeout=50, key_prefix='get_list')
def get_list():
print 'method get_list called'
return ['a','b','c','d','e'] @app.route('/list')
def list():
return ', '. join(get_list())
我们访问”/list”地址时,第一次控制台上会有”method called”输出,第二次就不会了,说明缓存起效了。装饰普通函数时必须指定明确的”key_prefix”参数,因为它不像视图函数,可以使用请求路径”request.path”作为缓存项的键值。如果函数带参数,对于不同的参数调用,都会使用同一缓存项,即返回结果一样。Flask-Cache还提供了另一个装饰器方法”cache.memoize()”,它与”cache.cached()”的区别就是它会将函数的参数也放在缓存项的键值中:
@cache.memoize(timeout=50)
def create_list(num):
print 'method create_list called'
l = []
for i in range(num):
l.append(str(i))
return l @app.route('/list/<int:num>')
def list(num):
return ', '.join(create_list(num))
我们再次访问”/list”地址,对于不同的参数,”method called”会一直在控制台上打印出,而对于相同的参数,第二次就不会打印了。所以对于带参数的函数,你要使用”cache.memoize()”装饰器,而对于不带参数的函数,它同”cache.cached()”基本上一样。”cache.memoize()”装饰器也有三个参数,”timeout”和”unless”参数同”cache.cached()”一样,就是第二个参数”make_name”比较特别。它是一个回调函数,传入的是被装饰的函数名,返回是一个字符串,会被作为缓存项键值的一部分,如果不设,就直接使用函数名。
删除缓存
对于普通缓存,你可以使用”delete()”方法来删除缓存项,而对于”memoize”缓存,你需要使用”delete_memoized”方法。如果想清除所有缓存,可以使用”clear()”方法。
cache.delete('get_list')                     # 删除'get_list'缓存项
cache.delete_many('get_list', 'view_hello')  # 同时删除'get_list'和'view_hello'缓存项
cache.delete_memoized('create_list', 5)      # 删除调用'create_list'函数并且参数为5的缓存项
cache.clear()                                # 清理所有缓存
Jinja2模板中使用缓存
其实在Jinja2模板中,我们还可以使用”{% cache %}”语句来缓存模板代码块:
{% cache 50, 'temp' %}
<p>This is under cache</p>
{% endcache %}
这样”{% cache %}”和”{% endcache %}”语句中所包括的内容就会被缓存起来。”{% cache %}”语句的第一个参数是”timeout”过期时间,默认为永不过期;第二个参数指定了缓存项的键值,如果不设,键值就是”模板文件路径”+”缓存块的第一行”。上例中,我们设了键值是”temp”,然后在代码中,我们可以这样获取缓存项实际的键值:
from flask_cache import make_template_fragment_key
key = make_template_fragment_key('temp')
打印出来看看,你会发现实际的键值其实是”_template_fragment_cache_temp”。如果你要删除该缓存项,记得要传入实际的键值,而不是模板上定义的’temp’。
Flask 扩展 缓存的更多相关文章
- Inside Flask - flask 扩展加载过程
		Inside Flask - flask 扩展加载过程 flask 扩展(插件)通常是以 flask_<扩展名字> 为扩展的 python 包名,而使用时,可用 import flask. ... 
- Flask從入門到入土(二)——請求响应與Flask扩展
		———————————————————————————————————————————————————————————— 一.程序和請求上下文 Flask從客戶端收到請求時,要讓視圖函數能訪問一些對象 ... 
- Flask 扩展 自定义扩展
		创建一个为视图访问加日志的扩展Flask-Logging,并从中了解到写Flask扩展的规范. 创建工程 先创建一个工程,目录结构如下: flask-logging/ ├ LICENSE # 授权说明 ... 
- Flask从入门到精通之flask扩展
		Flask被设计成可扩展形式,因此并没有提供一些重要的功能,比如数据库和用户认证,所以开发者可以自由选择最适合程序的包,或者按需求自行开发.社区成员开发了大量不同用途的扩展,如果这还不能满足需求,你还 ... 
- Flask扩展实现HTTP令牌token认证HTTPTokenAuth
		Token认证 在restful设计中,用户认证模式通常使用json web token,而不会使用传统的HTTP Basic认证(传入账号密码) token认证模式如下:在请求header中加入to ... 
- 2.6、Flask扩展
		Flask 被设计为可扩展形式,故而没有提供一些重要的功能,例如数据库和用户认证,所以开发者可以自由选择最适合程序的包,或者按需求自行开发. 社区成员开发了大量不同用途的扩展,如果这还不能满足需求,你 ... 
- Flask基础(13)-->Flask扩展Flask-Script
		Flask基础(12)-->Flask扩展Flask-Script # 前提是安装了Flask-Script # 联网运行 pip install flask-script from flask ... 
- flask扩展系列之 - 访问速度限制
		flask-limiter 是一个对客户端的访问速率进行限制的flask扩展.可以自定义一些访问的(速度)限制条件来把那些触发限制的请求拒之门外.一般常用来进行对爬虫的限制. 下面就常见的用法,举了一 ... 
- Flask扩展 -- flask-mail
		电子邮件是最常用的通信方式之一.虽然Python标准库中的smtplib包可用在Flask程序中发送电子邮件,但包装了smtplib的Flask-Mail扩展能更好的和Flask集成. 1.安装Fla ... 
随机推荐
- Linux进行AES加密每次结果都不一致并且解密失败报错
			1. 现象 windows操作系统下进行"123456"的AES加密 encrypted message is below : QLNYZyjRnKF/zxAjzDt/lw== d ... 
- 第四篇:Web框架 - Django
			前言 Django是一个开放源代码的Web应用框架,由Python写成.它和J2EE一样,采用了MVC的软件设计模式,即模型M,视图V和控制器C. 本文将讲解DJango框架,并从实际应用的角度讲解一 ... 
- 【洛谷1131】【ZJOI2007】时态同步
			题面 题目描述 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字1,2,3-.进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路板的任何两 ... 
- C# + Javascript   实现评论回复功能
			首先先介绍一下前台 <script type="text/javascript"> function openWindow() { window.open(" ... 
- 2018java平均工资,想转行学java的快点上车
			很多人选择工作的原因很简单:要么有钱,要么自己开心,当然绝大多数人是既没有钱也不开心...(现实就是这么残酷).哪有钱多事少的活,请告诉我,我第一个去!!我想大部分人对java充满好奇的一个原因就是钱 ... 
- 进程互斥 Peterson算法
			转自http://blog.csdn.net/l294265421/article/details/46674847 假设有两个进程需要互斥的访问某一个临界区. Peterson算法的形式如下: en ... 
- Eclipse Web项目配置
			1.每次重开workspace都要重新配置一次 2.new web project之前配置 3.Windows-Preferences-(所有都要记得Apply) General Maven P. ... 
- MyBatis延迟加载和缓存
			一.延迟加载 1.主对象的加载: 根本没有延迟的概念,都是直接加载. 2.关联对象的加载时机: 01.直接加载: 访问主对象,关联对象也要加载 02.侵入式延迟: 访问主对象,并不加载关联对象 访问主 ... 
- 【OpenCV-Python:实现人脸、人眼、嘴巴识别】实战(一)
			AI时代的到来,手机上的APP开始应用人脸识别去完成事情,如iphoneX的人脸解锁,百度自动贩卖机的人脸识别系统进行支付,支付宝的人脸识别登录等,提高了使用软件的易用性,但也因为其便利性,在某些市面 ... 
- pycharm中的光标变粗的问题
			pycharm中的光标变粗后不能自动打成对的小括号和中括号及引号---->解决办法:按下insert键 按下:insert键进行切换 
