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 中。

注意:

cached()装饰器相比, memoize()的功能是一样的,

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_fieldrender_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 对象,您不需要指定整个导入字符串,只需指定以下名称之一。

内置缓存类型:

  • NullCache(默认;旧名称为null
  • SimpleCache(旧名称很简单
  • FileSystemCache(旧名称是 filesystem
  • RedisCache(需要redis;旧名称是 redis
  • RedisSentinelCache(需要redis;旧名称是redissentinel
  • RedisClusterCache(需要redis和rediscluster;旧名称是rediscluster
  • UWSGICache(需要uwsgi;旧名称是 uwsgi
  • MemcachedCache(需要 pylibmc 或 memcache;旧名称是memcached或 gaememcached
  • SASLMemcachedCache(需要 pylibmc;旧名称是saslmemcached
  • SpreadSASLMemcachedCache(需要pylibmc;旧名称是 spreadsaslmemcached
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_HOSTRedis 服务器主机。仅用于 RedisCache。
CACHE_REDIS_PORTRedis 服务器端口。默认值为 6379。仅用于 RedisCache。
CACHE_REDIS_PASSWORD服务器的 Redis 密码。仅用于 RedisCache 和 RedisSentinelCache。
CACHE_REDIS_DBRedis db(从零开始的数字索引)。默认为 0。仅用于 RedisCache 和 RedisSentinelCache。
CACHE_REDIS_SENTINELSRedis 哨兵地址的列表或元组。仅用于 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_TYPENullCache使用此类型。旧名称null 已弃用,将在 Flask-Caching 2.0 中删除。

不缓存的缓存

  • CACHE_DEFAULT_TIMEOUT

在 1.9.1 版更改:弃用旧名称而只使用类名称。


简单缓存

设置CACHE_TYPESimpleCache使用此类型。旧名称 simple已弃用,将在 Flask-Caching 2.0 中删除。

使用本地 python 字典进行缓存。这不是真正的线程安全。

相关配置值

  • CACHE_DEFAULT_TIMEOUT
  • CACHE_IGNORE_ERRORS
  • CACHE_THRESHOLD

在 1.9.1 版更改:弃用旧名称而只使用类名称。


文件系统缓存

设置CACHE_TYPEFileSystemCache使用此类型。旧名称 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_TYPERedisCache使用此类型。旧名称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_TYPERedisSentinel使用此类型。旧名称 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_TYPERedisClusterCache使用此类型。旧名称 rediscluster已弃用,将在 Flask-Caching 2.0 中删除。

  • CACHE_KEY_PREFIX
  • CACHE_REDIS_CLUSTER
  • CACHE_REDIS_PASSWORD

CACHE_OPTIONS 中的条目作为 **kwargs

在 1.9.1 版更改:弃用旧名称而只使用类名称。


内存缓存

设置CACHE_TYPEMemcachedCache使用此类型。旧名称 memcachedgaememcached已弃用,并将在 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_TYPESASLMemcachedCache使用此类型。旧名称 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_TYPESpreadSASLMemcachedCache使用此类型。旧名称spreadsaslmemcached已弃用,将在 Flask-Caching 2.0 中删除。

但是,与 SASLMemcachedCache 相同,如果它大于 memcached 阈值(默认情况下为 1M),则它具有跨多个键传播值的能力。使用Pickle。

0.11 版中的新功能。

在1.1.0版本更改:重命名spreadsaslmemcachedcachespreadsaslmemcached保持一致性的缘故。

在 1.9.1 版更改:弃用旧名称而只使用类名称。


UWSGICache 

警告

UWSGICache未维护或测试。使用风险自负。


设置CACHE_TYPEflask_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 配置选项的值

笔记

argsandkwargs在实例化缓存对象时不展开,即它们不作为*argsand传入**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