重寫flask-cache的cache_key生成機制
阿新 • • 發佈:2018-11-26
flask-cache 預設將 (view/%s) % request.path 作為cache_key,但有時並不能滿足實際需要,例如當url中有引數,且引數也要作為cache_key的一部分時,那麼不同的引數就會共用一個快取,這顯然是錯的。
例如有一個路由 /item
, /item?page=0 表示第一頁的資料, /item?page=1 表示第二頁的資料。我們想把這兩個url生成兩個不同的cache_key,按照預設生成cache_key的方式只會生成同一個, 那就是view//item。我們可能會嘗試增加key_prefix引數,但是我們怎麼拿到page引數呢,因為獲取url引數不能脫離request上下文環境,所以在裝飾器中是拿不到的。
我們只能重寫預設的cache_key生成機制,原始碼中是這樣的:
def make_cache_key(*args, **kwargs):
if callable(key_prefix):
cache_key = key_prefix()
elif '%s' in key_prefix:
cache_key = key_prefix % request. path
else:
cache_key = key_prefix
return cache_key
我們可以根據需要改變這個方式,在這裡我們只需要把request.path 改成 request.url 即可。但是
, 怎麼改呢? 直接去改原始碼嗎?這涉及到python中修改第三方庫的方式,主要有三種方式,第一種是將原始碼fork下來修改後自己釋出,第二種是用類繼承的方式,第三種是monkey patch (猴子補丁)的方式。 猴子補丁 第三方庫修改方式
這裡我用的是第三種(勉強算吧,我也才開始接觸) 。首先,把cached方法copy到一個單獨的模組中,然後根據需要修改。然後將修改後的方法新增到cache例項中以覆蓋之前的方法。例如:
from app.utils.cache import cached, delete_like
from flask_cache import Cache
cache = Cache(config={'CACHE_TYPE': 'simple'})
cache.init_app(app) # 註冊快取
# 重寫快取key_prefix機制
cache.cached = cached
注意
,因為我們重寫的是例項方法,例項方法的第一個引數是self,所以我們在呼叫這個方法時要將cache例項本身也作為引數傳進去。例如:
@cache.cached(cache, timeout=300, key_prefix='get_item_%s')
[完]