Flask-Caching教程
Flask-Caching是一个Flask扩展,增加了各种后端任何Flask应用程序缓存的支持。除了通过统一的 API为所有werkzeug的原始缓存后端提供支持外 ,还可以通过对类进行子flask_caching.backends.base.BaseCache
类化来开发自己的缓存后端 。
一、版本支持
从 1.8 开始,Flask-Caching 仅支持 Python 3.5+。
二、安装
使用以下命令安装扩展:
$ pip install Flask-Caching
三、设置
Flask-Caching是通过创建一个Cache
实例进行使用,示例代码如下:
from flask import Flask
from flask_caching import Cache
config = {
"DEBUG": True, # some Flask specific configs
"CACHE_TYPE": "SimpleCache", # Flask-Caching related configs
"CACHE_DEFAULT_TIMEOUT": 300
}
app = Flask(__name__)
# tell Flask to use the above defined config
app.config.from_mapping(config)
cache = Cache(app)
也可以先创建Cache
变量,然后在配置时使用init_app方法初始化实例,代码如下 :
cache = Cache(config={'CACHE_TYPE': 'SimpleCache'})
app = Flask(__name__)
cache.init_app(app)
也可以使用配置字典,如果有多个Cache
实例,每个实例都可以配置不同的后端:
#: Method A: During instantiation of class
cache = Cache(config={'CACHE_TYPE': 'SimpleCache'})
#: Method B: During init_app call
cache.init_app(app, config={'CACHE_TYPE': 'SimpleCache'})
0.7 版中的新功能。
四、缓存视图函数
要缓存视图函数,可以使用cached()
装饰器。默认情况下,此装饰器将 request.path 用于 cache_key:
@app.route("/")
@cache.cached(timeout=50)
def index():
return render_template('index.html')
缓存装饰器有另一个可选参数,称为unless
. 此参数接受返回 True 或 False 的可调用对象。如果unless
返回, True
那么它将完全绕过缓存机制。
警告
在
cached
视图上使用时,请注意一定要将其放在 Flask 的@route
装饰器和您的函数定义之间。例子:@app.route('/') @cache.cached(timeout=50) def index(): return 'Cached for 50s'如果您反转两个装饰器,将缓存的是
@route
装饰器的结果 ,而不是您的视图函数的结果。
五、缓存其他函数
使用相同的@cached
装饰器,可以缓存其他非视图相关函数的结果。唯一的规定是你替换 key_prefix
,否则它将使用 request.path cache_key 。键控制应该从缓存中获取什么。例如,如果缓存中不存在键,则会在缓存中创建一个新的键值条目。否则将返回键的值(即缓存的结果):
@cache.cached(timeout=50, key_prefix='all_comments')
def get_all_comments():
comments = do_serious_dbio()
return [x.author for x in comments]
cached_comments = get_all_comments()
六、记忆化
在记忆化中,使用memoize装饰器实现缓存功能,函数参数也包含在 cache_key 中。
注意:
Memoize 也是为类的方法设计的,他可以将'self' 或 'cls' 参数作为缓存键的一部分。
memoization 背后的理论是,如果您有一个函数需要在一个请求中多次调用,它只会在第一次使用这些参数调用该函数时计算。例如,确定用户是否具有角色的 sqlalchemy 对象。您可能需要在单个请求期间多次调用此函数。为了避免每次需要此信息时访问数据库,您可以执行以下操作:
class Person(db.Model):
@cache.memoize(50)
def has_membership(self, role_id):
return Group.query.filter_by(user=self, role_id=role_id).count() >= 1
警告
使用可变对象(类等)作为缓存键的一部分可能会变得棘手。建议不要将对象实例传递给记忆化函数。但是,memoize 确实对传入的参数执行 repr() ,因此如果对象具有 __repr__ 函数,该函数返回该对象的唯一标识字符串,则该函数将用作缓存键的一部分。
例如,一个 sqlalchemy person 对象返回数据库 id 作为唯一标识符的一部分:
class Person(db.Model):
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, self.id)
删除memoize缓存
0.2 版中的新功能。
您可能需要按功能删除缓存。使用上面的示例,假设您更改用户的权限并将其分配给角色,但现在您需要重新计算他们是否具有某些成员资格。您可以使用以下delete_memoized()
功能执行此操作:
cache.delete_memoized(user_has_membership)
注意:
如果仅将函数名称作为参数给出,则它的所有记忆版本都将无效。但是,您可以通过提供与缓存时相同的参数值来删除特定缓存。在以下示例中,仅
user
删除了-role 缓存:
user_has_membership('demo', 'admin') user_has_membership('demo', 'user') cache.delete_memoized(user_has_membership, 'demo', 'user')
警告
如果一个类方法被记忆,你必须提供
class
作为第一个*args
参数。
class Foobar(object): @classmethod @cache.memoize(5) def big_foo(cls, a, b): return a + b + random.randrange(0, 100000) cache.delete_memoized(Foobar.big_foo, Foobar, 5, 2)
七、缓存 Jinja2 片段
用法:
{% cache [timeout [,[key1, [key2, ...]]]] %} ... {% endcache %}
默认情况下,使用“模板文件路径”+“块起始行”的值作为缓存键。此外,可以手动设置密钥名称。键连接在一起形成单个字符串,可用于避免在不同模板中评估相同的块。
将超时设置None
为无超时,但使用自定义键:
{% cache None, "key" %} ... {% endcache %}
将超时设置del
为删除缓存值:
{% cache 'del', key1 %} ... {% endcache %}
如果提供了键,您可以轻松生成模板片段键并将其从模板上下文之外删除:
from flask_caching import make_template_fragment_key
key = make_template_fragment_key("key1", vary_on=["key2", "key3"])
cache.delete(key)
考虑到我们有render_form_field
和render_submit
宏:
{% cache 60*5 %} <div> <form> {% render_form_field(form.username) %} {% render_submit() %} </form> </div> {% endcache %}
八、清除缓存
见clear()。
这是一个用于清空应用程序缓存的示例脚本:
from flask_caching import Cache
from yourapp import app, your_cache_config
cache = Cache()
def main():
cache.init_app(app, config=your_cache_config)
with app.app_context():
cache.clear()
if __name__ == '__main__':
main()
警告
一些后端实现不支持完全清除缓存。此外,如果您不使用键前缀,某些实现(例如 Redis)将刷新整个数据库。确保您没有在缓存数据库中存储任何其他数据。
九、显式缓存数据
可以使用Cache.set()
, 和Cache.get()
直接等代理方法显式缓存数据 。通过Cache
该类还有许多其他的代理方法可用。
例如:
@app.route("/html")
@app.route("/html/<foo>")
def html(foo=None):
if foo is not None:
cache.set("foo", foo)
bar = cache.get("foo")
return render_template_string(
"<html><body>foo cache: {{bar}}</body></html>", bar=bar
)
十、配置 Flask 缓存
Flask-Caching 存在以下配置值:
CACHE_TYPE |
指定要使用的缓存对象类型。这是将被导入和实例化的导入字符串。假设导入对象是一个函数,它将返回一个符合缓存 API 的缓存对象。 对于flask_caching.backends.cache 对象,您不需要指定整个导入字符串,只需指定以下名称之一。 内置缓存类型:
|
CACHE_NO_NULL_WARNING |
使用缓存类型“null”时使警告消息静音。 |
CACHE_ARGS |
在缓存类实例化期间解压和传递的可选列表。 |
CACHE_OPTIONS |
在缓存类实例化期间传递的可选字典。 |
CACHE_DEFAULT_TIMEOUT |
如果未指定超时,则使用的默认超时。时间单位是秒。 |
CACHE_IGNORE_ERRORS |
如果设置为任何在删除过程中发生的错误将被忽略。但是,如果设置为False 它,它将在第一个错误时停止。此选项仅与后端文件系统和简单的. 默认为False . |
CACHE_THRESHOLD |
缓存在开始删除一些之前将存储的最大项目数。仅用于 SimpleCache 和 FileSystemCache |
CACHE_KEY_PREFIX |
在所有键之前添加的前缀。这使得可以为不同的应用程序使用相同的 memcached 服务器。仅用于 RedisCache 和 MemcachedCache |
CACHE_SOURCE_CHECK |
应用于函数装饰器的默认条件,用于控制在形成用作缓存键的哈希时是否应包含函数的源代码。这确保了如果源代码发生变化,即使参数相同,在调用新函数时也不会返回缓存的值。默认为False . |
CACHE_UWSGI_NAME |
要连接的uwsgi缓存实例的名称,例如:mycache @ localhost :3031,默认为空字符串,表示 uWSGI 将缓存在本地实例中。如果缓存与 werkzeug 应用程序在同一个实例中,您只需提供缓存的名称。 |
CACHE_MEMCACHED_SERVERS |
服务器地址的列表或元组。仅用于 MemcachedCache |
CACHE_MEMCACHED_USERNAME |
使用 memcached 进行 SASL 身份验证的用户名。仅用于 SASLMemcachedCache |
CACHE_MEMCACHED_PASSWORD |
使用 memcached 进行 SASL 身份验证的密码。仅用于 SASLMemcachedCache |
CACHE_REDIS_HOST |
Redis 服务器主机。仅用于 RedisCache。 |
CACHE_REDIS_PORT |
Redis 服务器端口。默认值为 6379。仅用于 RedisCache。 |
CACHE_REDIS_PASSWORD |
服务器的 Redis 密码。仅用于 RedisCache 和 RedisSentinelCache。 |
CACHE_REDIS_DB |
Redis db(从零开始的数字索引)。默认为 0。仅用于 RedisCache 和 RedisSentinelCache。 |
CACHE_REDIS_SENTINELS |
Redis 哨兵地址的列表或元组。仅用于 RedisSentinelCache。 |
CACHE_REDIS_SENTINEL_MASTER |
哨兵配置中主服务器的名称。仅用于 RedisSentinelCache。 |
CACHE_REDIS_CLUSTER |
一串逗号分隔的 Redis 集群节点地址。例如 host1:port1,host2:port2,host3:port3 。仅用于 RedisClusterCache。 |
CACHE_DIR |
存储缓存的目录。仅用于 FileSystemCache。 |
CACHE_REDIS_URL |
连接到 Redis 服务器的 URL。例子redis://user:password@localhost:6379/2 。支持协议redis:// , rediss:// (redis over TLS) 和 unix:// . 查看有关 URL 支持的更多信息 [此处]( http://redis-py.readthedocs.io/en/latest/index.html#redis.ConnectionPool.from_url )。仅用于 RedisCache。 |
十一、内置缓存后端
空缓存
设置CACHE_TYPE
为NullCache
使用此类型。旧名称null
已弃用,将在 Flask-Caching 2.0 中删除。
不缓存的缓存
- CACHE_DEFAULT_TIMEOUT
在 1.9.1 版更改:弃用旧名称而只使用类名称。
简单缓存
设置CACHE_TYPE
为SimpleCache
使用此类型。旧名称 simple
已弃用,将在 Flask-Caching 2.0 中删除。
使用本地 python 字典进行缓存。这不是真正的线程安全。
相关配置值
- CACHE_DEFAULT_TIMEOUT
- CACHE_IGNORE_ERRORS
- CACHE_THRESHOLD
在 1.9.1 版更改:弃用旧名称而只使用类名称。
文件系统缓存
设置CACHE_TYPE
为FileSystemCache
使用此类型。旧名称 filesystem
已弃用,将在 Flask-Caching 2.0 中删除。
使用文件系统存储缓存值
- CACHE_DEFAULT_TIMEOUT
- CACHE_IGNORE_ERRORS
- 缓存目录
- CACHE_THRESHOLD
- CACHE_OPTIONS
在 CACHE_OPTIONS: mode 中有一个有效的条目,它应该是一个 3 位的 linux 风格的权限八进制模式。
在 1.9.1 版更改:弃用旧名称而只使用类名称。
RedisCache
设置CACHE_TYPE
为RedisCache
使用此类型。旧名称redis
已弃用,将在 Flask-Caching 2.0 中删除。
- CACHE_DEFAULT_TIMEOUT
- CACHE_KEY_PREFIX
- CACHE_OPTIONS
- CACHE_REDIS_HOST
- CACHE_REDIS_PORT
- CACHE_REDIS_PASSWORD
- CACHE_REDIS_DB
- CACHE_REDIS_URL
CACHE_OPTIONS 中的条目作为 **kwargs
在 1.9.1 版更改:弃用旧名称而只使用类名称。
RedisSentinelCache
设置CACHE_TYPE
为RedisSentinel
使用此类型。旧名称 redissentinel
已弃用,将在 Flask-Caching 2.0 中删除。
- CACHE_KEY_PREFIX
- CACHE_REDIS_SENTINELS
- CACHE_REDIS_SENTINEL_MASTER
- CACHE_REDIS_PASSWORD
- CACHE_REDIS_DB
CACHE_OPTIONS 中的条目作为 **kwargs
在 1.9.1 版更改:弃用旧名称而只使用类名称。
RedisClusterCache
设置CACHE_TYPE
为RedisClusterCache
使用此类型。旧名称 rediscluster
已弃用,将在 Flask-Caching 2.0 中删除。
- CACHE_KEY_PREFIX
- CACHE_REDIS_CLUSTER
- CACHE_REDIS_PASSWORD
CACHE_OPTIONS 中的条目作为 **kwargs
在 1.9.1 版更改:弃用旧名称而只使用类名称。
内存缓存
设置CACHE_TYPE
为MemcachedCache
使用此类型。旧名称 memcached
和gaememcached
已弃用,并将在 Flask-Caching 2.0 中删除。
使用 memcached 服务器作为后端。支持 pylibmc 或 memcache 或谷歌应用引擎 memcache 库。
相关配置值
- CACHE_DEFAULT_TIMEOUT
- CACHE_KEY_PREFIX
- CACHE_MEMCACHED_SERVERS
注意:
Flask-Caching 不会将额外的配置选项传递给 memcached 后端。要向这些缓存添加其他配置,请在实例化后直接在对象上设置配置选项:
from flask_caching import Cache cache = Cache() # Can't configure the client yet... cache.init_app(flask_app, {"CACHE_TYPE": "memcached"}) # Break convention and set options on the _client object # directly. For pylibmc behaviors: cache.cache._client.behaviors({"tcp_nodelay": True})
或者,请参阅自定义缓存后端。
在 1.9.1 版更改:弃用旧名称而只使用类名称。
SASLMemcachedCache
设置CACHE_TYPE
为SASLMemcachedCache
使用此类型。旧名称 saslmemcached
已弃用,将在 Flask-Caching 2.0 中删除。
使用 memcached 服务器作为后端。旨在与启用 SASL 的 memcached 服务器连接一起使用。pylibmc 是必需的,并且 libmemcached 必须支持 SASL。
相关配置值
- CACHE_DEFAULT_TIMEOUT
- CACHE_KEY_PREFIX
- CACHE_OPTIONS
- CACHE_MEMCACHED_SERVERS
- CACHE_MEMCACHED_USERNAME
- CACHE_MEMCACHED_PASSWORD
笔记:
与 MemcachedCache 不同,SASLMemcachedCache 可以使用 CACHE_OPTIONS 进行配置。
0.10 版中的新功能。
在 1.9.1 版更改:弃用旧名称而只使用类名称。
SpreadSASLMemcachedCache
设置CACHE_TYPE
为SpreadSASLMemcachedCache
使用此类型。旧名称spreadsaslmemcached
已弃用,将在 Flask-Caching 2.0 中删除。
但是,与 SASLMemcachedCache 相同,如果它大于 memcached 阈值(默认情况下为 1M),则它具有跨多个键传播值的能力。使用Pickle。
0.11 版中的新功能。
在1.1.0版本更改:重命名spreadsaslmemcachedcache
以spreadsaslmemcached
保持一致性的缘故。
在 1.9.1 版更改:弃用旧名称而只使用类名称。
UWSGICache
警告
UWSGICache
未维护或测试。使用风险自负。
设置CACHE_TYPE
为flask_caching.contrib.uwsgicache.UWSGICache
使用此类型。您还必须设置CACHE_UWSGI_NAME
为您在 uWSGI 配置中设置的缓存名称。
十二、自定义缓存后端
通过公开可以实例化并返回缓存对象的函数,您可以轻松添加自己的自定义缓存后端。CACHE_TYPE
将是您的自定义缓存类型的导入字符串。如果不是 的子类 flask_caching.backends.cache.BaseCache
,Flask-Caching 将使用三个参数调用它:
app
,正在为其初始化缓存的 Flask 应用程序对象args
, CACHE_ARGS 配置选项的值kwargs
, CACHE_OPTIONS 配置选项的值
笔记
args
andkwargs
在实例化缓存对象时不展开,即它们不作为*args
and传入**kwargs
,但它们是 CACHE_ARGS 和 CACHE_OPTIONS 配置选项的确切值(但是,CACHE_ARGS 被转换为列表)。
但是,您的自定义缓存应该是flask_caching.backends.cache.BaseCache
该类的子 类,以便它提供所有可用的必要方法。
在 1.9.1 版更改:如果您的自定义缓存类型是的子类 flask_caching.backends.cache.BaseCache
,Flask-Caching 将factory
使用与上面列出的相同的参数调用其类方法,而不是直接实例化该类。除非被覆盖,否则BaseCache.factory
只需实例化对象而不向其传递任何参数。内置缓存类已经覆盖了它来模仿旧的、基于函数的缓存实例化,所以如果你子类化了一些不是的东西 flask_caching.backends.cache.BaseCache
,你可能需要查阅源代码来看看你的类是否仍然兼容。
一个示例实现:
#: the_app/custom.py
class RedisCache(BaseCache):
def __init__(self, servers, default_timeout=500):
pass
@classmethod
def factory(cls, app, args, kwargs):
args.append(app.config['REDIS_SERVERS'])
return cls(*args, **kwargs)
通过这个例子,你CACHE_TYPE
可能是the_app.custom.RedisCache
不过,CACHE_TYPE 不必直接指向缓存类。如果在库上启用了 SASL,则更改二进制设置并提供用户名/密码的示例 PylibMC 缓存实现:
#: the_app/custom.py
def pylibmccache(app, config, args, kwargs):
return pylibmc.Client(servers=config['CACHE_MEMCACHED_SERVERS'],
username=config['CACHE_MEMCACHED_USERNAME'],
password=config['CACHE_MEMCACHED_PASSWORD'],
binary=True)
通过这个例子,你CACHE_TYPE
可能是the_app.custom.pylibmccache