1
头图

基本用法

基于 Flask 应用,难免会用到 Flask-cache (或 Flask-cacheing,两者API 基本相同)。它通过装饰器,非常优雅地实现了函数调用的缓存。装饰器可以直接加在 view function ,或者普通 function 上,类似下面的样子:

@app.route('/demo/student/all', methods=['GET'])
@cache.cached(timeout=600)
def get():
    students = Student.query.all()
    return response_ok(students)

(如果函数有参数,并且希望针对不同实参值,做不同的缓存,那就用 _@cache.memerized _装饰器)
添加了装饰器的函数,在第一次被调用之后,返回值就被在缓存有效期内,示例中的timeout 参数,保证了缓存在600秒后超时失效,再次调用函数本体获得最新数据。

view function 缓存控制

但有时我们需要控制这个缓存的更新——比如上面的例子中,每次新增一个学生、或者更改学生数据,就重新刷新一下缓存,而不需要等它自然超时。这时就需要显式调用 delete 函数,例如:

del_res = cache.delete('/demo/student/all')

对于 view function 来说,这里 delete 的参数,就恰好等于 route 里的 path,如果 route 来自于一个上级的 blueprint,要记得把上级 path 带上。
如果你要指定 cache 的 key,可以加上 key_prefix 参数,类似下面这样:

@app.route('/demo/student/all', methods=['GET'])
@cache.cached(timeout=600, key_prefix='res_student_all')
def get():
    ...

注意第一个坑来了:因为名字里有个 prefix,你可能会觉得它是 key 的前缀,删除的时候,会想着怎么组合一下这个参数和 path;然而实际上却不用任何组合,path 在这里已经无效了,删除时直接用这个 key_prefix 当参数就可以:

del_res = cache.delete('res_student_all')

事实上,这个 key_prefix 既不是 key 的前缀,也不是整个 key,它应该叫 key 的后缀更合理,真正保存的 key(存在那里取决于配置,可以有内存缓存SimpleCache、redis缓存等等)前缀是这个样子的:**flask_cache_**,而无论是 path 还是 key_prefix,都会在 hash 之后拼接在后面。

普通 function 缓存控制

简单函数

如果是普通的 function,要使用 @cache.memoize 装饰器,同样支持 timeout 参数,如下:

@cache.memoize(timeout=60)
def get_number():
    return 5

删除 memoize 要更直观一些,直接传函数就可以啦:

del_res = cache.delete_memoize(get_number)

如果该函数有参数:

@cache.memoize(timeout=60)
def get_number(x):
    return 5 + x

删除时加参数,表示只删除这个参数对应的缓存,不加参数,表示删除该函数的所有实参值对应缓存:

del_res = cache.delete_memoize(get_number, 5)    # 只删除x=5的缓存
del_res = cache.delete_memoize(get_number)    # 删除所有 get_number 缓存

类函数

这时第二个坑来了,如果这是个类函数呢?

@cache.memoize(timeout=60)
class Calc:
    @classmethod
    def get_number(x):
        return 5 + x

删除时,只传函数名,或者函数名加参数,是删不掉的:

del_res = cache.delete_memoize(Calc.get_number, 5)    # 无法删除x=5的缓存
del_res = cache.delete_memoize(Calc.get_number)    # 无法删除所有 get_number 缓存

官方文档说,“要把类当做第一个参数传进来”,这个的表述非常容易误解,实际上应该是参数列表里的第一个,所以要像下面这样传:

del_res = cache.delete_memoize(Calc.get_number, Calc, 5)    # 删除x=5的缓存
del_res = cache.delete_memoize(Calc.get_number, Calc)    # 删除所有 get_number 缓存

songofhawk
303 声望24 粉丝