1. 程式人生 > >重寫flask-cache的cache_key生成機制

重寫flask-cache的cache_key生成機制

      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')

      [完]