基本用法
基於 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 快取