Flask-Cache
安装
pip install Flask-Cache
配置
from flask import Flask
from flask_cache import Cacheapp = Flask(__name__)cache = Cache()
# 初始化 Cache 后设置
cache.init_app(app,config={'CACHE_TYPE': 'simple'})if __name__ == "__main__":app.run()
会发现运行出错。
接下来,解决这个错误,使app正常运行:
- ImportError: cannot import name 'cached_property' from 'werkzeug'
找到flask_cache\__init__.py
文件,如下所示:
from werkzeug import import_string
更改为:
from werkzeug.utils import import_string
2. ModuleNotFoundError: No module named 'flask.ext'
找到flask_cache\jinja2ext.py
文件,如下所示:
from flask.ext.cache import make_template_fragment_key
更改为:
from flask_cache import make_template_fragment_key
如果有多个 Cache
实例以及每一个实例都有不同后端的话(换句话说,就是每一个实例使用不用的缓存类型CACHE_TYPE),使用配置字典是十分有用的:
#: Method A: During instantiation of class
cache = Cache(config={'CACHE_TYPE': 'simple'})
#: Method B: During init_app call
cache.init_app(app, config={'CACHE_TYPE': 'simple'})
- ModuleNotFoundError: No module named 'werkzeug.contrib'
找到flask_cache\backends.py
文件,如下所示:
from werkzeug.contrib.cache import (BaseCache, NullCache, SimpleCache, MemcachedCache,
通过重新安装werkzeug解决。
pip install Werkzeug==0.15.1
缓存视图函数
使用装饰器 cached()
能够缓存视图函数。它在默认情况下使用请求路径(request.path)作为cache_key:
@cache.cached(timeout=50)
def index():return render_template('index.html')
该装饰器有一个可选的参数:unless
,它允许一个可调用的、返回值是True或者False的函数。如果 unless
返回 True
,将会完全忽略缓存机制(内置的缓存机制会完全不起作用)。
缓存其它函数
同样地,使用 @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()
Memoization(一种缓存技术)
在memoization中,函数参数同样包含cache_key。
如果函数不接受参数的话,cached()
和 memoize()
两者的作用是一样的。
Memoize同样也为类成员函数而设计,因为它根据 identity
将 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
使用可变对象(例如类)作为缓存键的一部分是十分棘手的。建议最好不要让一个对象的实例成为一个memoized函数。然而,memoize在处理参数的时候会执行repr(),因此如果一个对象有__repr__
函数,并且返回一个唯一标识该对象的字符串,它将能够作为缓存键的一部分。
例如,一个sqlalchemy person对象,它返回数据库的ID作为唯一标识符的一部分:
class Person(db.Model):def __repr__(self):return "%s(%s)" % (self.__class__.__name__, self.id)
删除memoize的缓存
在每个函数的基础上,可能需要删除缓存。使用上面的例子,能够改变用户权限,并将它们分配到一个角色,如果它们新拥有或者失去某些成员关系,现在你需要重新计算。能够用 delete_memoized()`函数来达到目的:
cache.delete_memoized('user_has_membership')
如果仅仅只有函数名作为参数,所有的memoized的版本将会无效的。然而,您可以删除特定的缓存提供缓存时相同的参数值。在下面的例子中,只有 user
角色缓存被删除:
user_has_membership('demo', 'admin')
user_has_membership('demo', 'user')cache.delete_memoized('user_has_membership', 'demo', 'user')
缓存Jinja2片段
- 用法
{% cache [timeout [,[key1, [key2, ...]]]] %}
...
{% endcache %}
默认情况下“模版文件路径”+“片段开始的函数”用来作为缓存键。同样键名是可以手动设置的。键名串联成一个字符串,这样能够用于避免同样的块在不同模版被重复计算。
设置 timeout 为 None,并且使用了自定义的键:
{% cache None "key" %}...
为了删除缓存值,为“del”设置超时时间:
{% cache 'del' %}...
如果提供键名,可以很容易地产生模版的片段密钥,从模板上下文外删除它:
from flask.ext.cache import make_template_fragment_key
key = make_template_fragment_key("key1", vary_on=["key2", "key3"])
cache.delete(key)
例子:
{% cache 60*5 %}<form>{% render_form_field form.username %}{% render_submit %}</form>{% endcache %}
清除缓存
下面的例子是一个用来清空应用缓存的脚本:
from flask.ext.cache import Cachefrom yourapp import app, your_cache_configcache = Cache()def main():cache.init_app(app, config=your_cache_config)with app.app_context():cache.clear()if __name__ == '__main__':main()
某些缓存类型不支持完全清空缓存。同样,如果你不使用键前缀,一些缓存类型将刷新整个数据库。请确保没有任何其他数据存储在缓存数据库中。
配置Flask-Cache
Flask-Cache有下面一些配置项:
CACHE_TYPE
指定哪些类型的缓存对象来使用。 这是一个输入字符串,将被导入并实例化。 它假设被导入的对象是一个依赖于werkzeug缓存API, 返回缓存对象的函数。
对于werkzeug.contrib.cache对象,不必给出完整的字符串, 只要是下列这些名称之一。
内建缓存类型:
- null: NullCache (default)
- simple: SimpleCache
- memcached: MemcachedCache (pylibmc or memcache required)
- gaememcached: GAEMemcachedCache
- redis: RedisCache (Werkzeug 0.7 required)
- filesystem: FileSystemCache
- saslmemcached: SASLMemcachedCache (pylibmc required)
参数 | 含义 |
---|---|
CACHE_NO_NULL_WARNING |
当使用的缓存类型是’null’,不会抛出警告信息。 |
CACHE_ARGS |
可选的列表,在缓存类实例化的时候会对该列表进行拆分以及传递(传参)。 |
CACHE_OPTIONS |
可选的字典,在缓存类实例化的时候会传递该字典(传参)。 |
CACHE_DEFAULT_TIMEOUT |
如果没有设置延迟时间,默认的延时时间会被使用。单位为秒。 |
CACHE_THRESHOLD |
最大的缓存条目数,超过该数会删除一些缓存条目。仅仅用于SimpleCache和 FileSystemCache。 |
CACHE_KEY_PREFIX |
所有键之前添加的前缀。 这使得它可以为不同的应用程序使用相同的memcached服务器。 仅仅用于RedisCache,MemcachedCache以及GAEMemcachedCache。 |
CACHE_MEMCACHED_SERVERS |
服务器地址列表或元组。仅用于MemcachedCache。 |
CACHE_MEMCACHED_USERNAME |
SASL与memcached服务器认证的用户名。 仅用于SASLMemcachedCache。 |
CACHE_MEMCACHED_PASSWORD |
SASL与memcached服务器认证的密码。 仅用于SASLMemcachedCache。 |
CACHE_REDIS_HOST |
Redis服务器的主机。仅用于RedisCache。 |
CACHE_REDIS_PORT |
Redis服务器的端口。默认是6379。仅用于RedisCache。 |
CACHE_REDIS_PASSWORD |
用于Redis服务器的密码。仅用于RedisCache。 |
CACHE_REDIS_DB |
Redis的db库 (基于零号索引)。默认是0。仅用于RedisCache。 |
CACHE_DIR |
存储缓存的目录。仅用于FileSystemCache。 |
CACHE_REDIS_URL |
连接到Redis服务器的URL。 例如:redis://user:[email protected]:6379/2 。 仅用于RedisCache。 |
此外,如果标准的Flask配置项 TESTING
使用并且设置为True的话, Flask-Cache 将只会使用NullCache作为缓存类型。
cache.init_app(app, config={ 'CACHE_TYPE' : 'redis','CACHE_REDIS_HOST':'xxxx', 'CACHE_REDIS_PORT':'xxxx'})
内建的缓存类型
NullCache – null
不缓存内容
- CACHE_ARGS
- CACHE_OPTIONS
SimpleCache – simple
使用本地Python字典缓存。这不是真正的线程安全。
相关配置
- CACHE_DEFAULT_TIMEOUT
- CACHE_THRESHOLD
- CACHE_ARGS
- CACHE_OPTIONS
FileSystemCache – filesystem
使用文件系统来存储缓存值
- CACHE_DEFAULT_TIMEOUT
- CACHE_DIR
- CACHE_THRESHOLD
- CACHE_ARGS
- CACHE_OPTIONS
MemcachedCache – memcached
使用memcached服务器作为后端。支持pylibmc或memcache或谷歌应用程序引擎的memcache库。
相关配置项
- CACHE_DEFAULT_TIMEOUT
- CACHE_KEY_PREFIX
- CACHE_MEMCACHED_SERVERS
- CACHE_ARGS
- CACHE_OPTIONS
GAEMemcachedCache – gaememcached
MemcachedCache一个不同的名称
SASLMemcachedCache – saslmemcached
使用memcached服务器作为后端。使用SASL建立与memcached服务器的连接。pylibmc是必须的,libmemcached必须支持SASL。
相关配置项
- CACHE_DEFAULT_TIMEOUT
- CACHE_KEY_PREFIX
- CACHE_MEMCACHED_SERVERS
- CACHE_MEMCACHED_USERNAME
- CACHE_MEMCACHED_PASSWORD
- CACHE_ARGS
- CACHE_OPTIONS
New in version 0.10.
SpreadSASLMemcachedCache – spreadsaslmemcachedcache
与SASLMemcachedCache一样,但是如果大于memcached的传输安全性,默认是1M,能够跨不同的键名缓存值。使用pickle模块。
New in version 0.11.
RedisCache – redis
- CACHE_DEFAULT_TIMEOUT
- CACHE_KEY_PREFIX
- CACHE_REDIS_HOST
- CACHE_REDIS_PORT
- CACHE_REDIS_PASSWORD
- CACHE_REDIS_DB
- CACHE_ARGS
- CACHE_OPTIONS
- CACHE_REDIS_URL
定制缓存类
from werkzeug.contrib.cache import BaseCacheclass MongoCache(BaseCache):def init(self, host='localhost', port=27017, username=None, password=None, default_timeout=500, **kwargs):BaseCache.init(self, default_timeout)if isinstance(host, str):try:from pymongo import MongoClientexcept ImportError:raise RuntimeError('no pymongo module found')self._client = MongoClient(host=host, port=port, username=username, password=password, **kwargs)else:self._client = host# 接下来使用pymongo实现BaseCache的各个接口passdef mongo(app, config, args, kwargs):"""这里处理app传进来的参数用来连接mongodb:param app::param config::param args::param kwargs::return:"""args.append(app.config['MONGO_SERVERS'])return MongoCache(*args, **kwargs)
flask-Caching
安装
pip install Flask-Caching
简单应用
from flask import Flask,render_template
from flask_caching import Cacheapp = Flask(__name__)cache = Cache()
cache.init_app(app,config={'CACHE_TYPE': 'simple'})@cache.cached(timeout=50)
@app.route('/')
def index():return "Hello World"if __name__ == "__main__":app.run()