W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
有時,緩存整個渲染頁面并不會帶來太多好處,事實上,這樣會很不方便。
或許,你的站點包含了一個視圖,它的結(jié)果依賴于許多費時的查詢,而且結(jié)果會隨著時間變化而改變。在這個情況下,使用站點或視圖緩存策略提供的全頁面緩存并不理想,因為不能緩存所有結(jié)果(一些數(shù)據(jù)經(jīng)常變動),不過你仍然可以緩存幾乎沒有變化的結(jié)果。
像這樣的情況,Django 公開了一個底層的緩存 API 。你可以使用這個 API 以任意級別粒度在緩存中存儲對象。你可以緩存任何可以安全的 pickle 的 Python 對象:模型對象的字符串、字典、列表,或者其他。
你可以通過類似字典一樣的 ?object: django.core.cache.caches
? 對象訪問在 ?CACHES
?配置的緩存。重復請求同一個線程里的同一個別名將返回同一個對象。
>>> from django.core.cache import caches
>>> cache1 = caches['myalias']
>>> cache2 = caches['myalias']
>>> cache1 is cache2
True
如果鍵名不存在,將會引發(fā) ?InvalidCacheBackendError
?錯誤。
為了支持線程安全,將為每個線程返回緩存后端的不同實例。
作為快捷方式,默認緩存可以通過 ?django.core.cache.cache
? 引用:
>>> from django.core.cache import cache
這個對象等價于 ?caches['default']
?
基本接口是:
>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'
?key
?是一個字符串,?value
?可以任何 picklable 形式的 Python 對象。
?timeout
?參數(shù)是可選的,默認為 ?CACHES
?中相應后端的 ?timeout
?參數(shù)。它是值存在緩存里的秒數(shù)。?timeout
?設置為 ?None
?時將永久緩存。?timeout
?為0將不緩存值。
如果對象不在緩存中,?cache.get()
? 將返回 ?None
?。
>>> # Wait 30 seconds for 'my_key' to expire...
>>> cache.get('my_key')
None
如果你需要確定對象是否存在于緩存中,并且你已經(jīng)存儲了一個字面值 ?None
?,使用一個前哨對象作為默認:
>>> sentinel = object()
>>> cache.get('my_key', sentinel) is sentinel
False
>>> # Wait 30 seconds for 'my_key' to expire...
>>> cache.get('my_key', sentinel) is sentinel
True
?cache.get()
?可以帶一個默認參數(shù)。如果對象不在緩存中,將返回指定的值。
>>> cache.get('my_key', 'has expired')
'has expired'
在鍵不存在的時候,使用 ?add()
? 方法可以添加鍵。它與 ?set()
? 帶有相同的參數(shù),但如果指定的鍵已經(jīng)存在,將不會嘗試更新緩存。
>>> cache.set('add_key', 'Initial value')
>>> cache.add('add_key', 'New value')
>>> cache.get('add_key')
'Initial value'
如果你想知道通過 ?add()
? 存儲的值是否在緩存中,你可以檢查返回值。如果值已保存,將返回 ?True
?,否則返回 ?False
?。
如果你想得到鍵值或者如果鍵不在緩存中時設置一個值,可以使用 ?get_or_set()
? 方法。它帶有和 ?get()
? 一樣的參數(shù),但默認是為那個鍵設置一個新緩存值,而不是返回:
>>> cache.get('my_new_key') # returns None
>>> cache.get_or_set('my_new_key', 'my new value', 100)
'my new value'
你也可以傳遞任何可調(diào)用的值作為默認值:
>>> import datetime
>>> cache.get_or_set('some-timestamp-key', datetime.datetime.now)
datetime.datetime(2014, 12, 11, 0, 15, 49, 457920)
這里也有 ?get_many()
? 接口,返回一個字典,其中包含你請求的鍵,這些鍵真實存在緩存中(并且沒過期):
>>> cache.set('a', 1)
>>> cache.set('b', 2)
>>> cache.set('c', 3)
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}
使用 ?set_many()
? 傳遞鍵值對的字典,可以更有效的設置多個值。
>>> cache.set_many({'a': 1, 'b': 2, 'c': 3})
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}
類似 ?cache.set()
?,?set_many()
? 帶有一個可選的 ?timeout
?參數(shù)。
在已支持的后端(memcached),?set_many()
? 會返回無法插入的鍵列表。
你可以使用 ?delete()
? 顯式地刪除鍵,以清空特定對象的緩存:
>>> cache.delete('a')
True
如果鍵被成功刪除,將返回? delete()
? ,否則返回 ?False
?。
如果你想一次性清除很多鍵,給 ?delete_many()
? 傳遞一個鍵列表即可刪除。
>>> cache.delete_many(['a', 'b', 'c'])
最后,如果你想刪除緩存里的所有鍵,使用 ?cache.clear()
?。注意,?clear()
?將刪除緩存里的 任何 鍵,不只是你應用里設置的那些鍵。
>>> cache.clear()
?cache.touch()
? 為鍵設置一個新的過期時間。比如,更新一個鍵為從現(xiàn)在起10秒鐘后過期:
>>> cache.touch('a', 10)
True
和其他方法一樣,?timeout
?參數(shù)是可選的,并且默認是 ?CACHES
?設置的相應后端的 ?TIMEOUT
?選項。
如果鍵被成功 ?touch()
?,將返回 ?True
?,否則返回 ?False
?。
你也可以使用分別使用 ?incr()
? 或 ?decr()
? 方法來遞增或遞減一個已經(jīng)存在的鍵的值。默認情況下,存在的緩存值將遞增或遞減1。通過為遞增/遞減的調(diào)用提供參數(shù)來指定其他遞增/遞減值。如果你試圖遞增或遞減一個不存在的緩存鍵,將會引發(fā) ?ValueError
?錯誤。
>>> cache.set('num', 1)
>>> cache.incr('num')
2
>>> cache.incr('num', 10)
12
>>> cache.decr('num')
11
>>> cache.decr('num', 5)
6
如果緩存后端已經(jīng)實現(xiàn)了 ?close()
? 方法,你可以關(guān)閉和緩存的連接。
>>> cache.close()
如果你正在服務器之間或者生產(chǎn)/開發(fā)緩存之間共享緩存實例,有可能會使得一個服務器使用另一個服務器的緩存數(shù)據(jù)。如果緩存數(shù)據(jù)格式是相同的,這會導致一些難以診斷的問題。
為了防止這個問題,Django 為單臺服務器提供了為所有緩存鍵提供前綴的方法。當一個特殊的緩存鍵被保存或檢索時,Django 會為緩存鍵自動添加 ?KEY_PREFIX
?緩存設置的前綴值。
要確保每個 Django 實例有不同的 ?KEY_PREFIX
?,這樣就保證緩存值不會發(fā)生沖突。
當更改使用緩存值的運行代碼時,你可能需要清除任何已存的緩存值。最簡單的方法是刷新整個緩存,但這會導致那些仍然有用且有效的緩存值。
Django 提供更好的方式來指向單個緩存值。Django 緩存框架有一個系統(tǒng)范圍的版本標識,需要在 ?VERSION
?緩存配置中指定。這個配置的值將自動與緩存前綴和用戶提供的緩存鍵組合起來獲取最終的緩存鍵。
默認情況下,任何鍵請求將自動包含站點默認緩存鍵版本。但是,早期的緩存函數(shù)都包含一個 ?version
?參數(shù),因此你可以指定 ?set
?還是 ?get
?特定緩存鍵的版本。舉例:
>>> # Set version 2 of a cache key
>>> cache.set('my_key', 'hello world!', version=2)
>>> # Get the default version (assuming version=1)
>>> cache.get('my_key')
None
>>> # Get version 2 of the same key
>>> cache.get('my_key', version=2)
'hello world!'
一個指定鍵的版本可以使用 ?incr_version()
? 和 ?decr_version()
?方法來遞增或遞減。這使得特定鍵會自動獲取新版本,而不影響其他鍵。繼續(xù)我們前面的例子:
>>> # Increment the version of 'my_key'
>>> cache.incr_version('my_key')
>>> # The default version still isn't available
>>> cache.get('my_key')
None
# Version 2 isn't available, either
>>> cache.get('my_key', version=2)
None
>>> # But version 3 *is* available
>>> cache.get('my_key', version=3)
'hello world!'
如前面兩節(jié)所述,用戶提供的緩存鍵不是單獨使用的,它是與緩存前綴和鍵版本組合后獲取最終緩存鍵。默認情況下,使用冒號連接這三部分生成最終的字符串:
def make_key(key, key_prefix, version):
return '%s:%s:%s' % (key_prefix, version, key)
如果你想用不同方式組合,或者應用其他處理來獲得最終鍵(比如,獲得關(guān)鍵部分的哈希摘要),那么你可以提供一個自定義的鍵函數(shù)。
?KEY_FUNCTION
?緩存設置指定一個與上面的 ?make_key()
? 原型匹配的函數(shù)路徑。如果提供,這個自定義鍵函數(shù)將代替默認的鍵組合函數(shù)來使用。
Memcached 作為最常用的緩存后端,不允許緩存鍵超過250個字符、包含空格或控制字符,并且使用這些鍵將會導致異常。為了增加代碼可移植性和最小驚訝,如果使用會導致 memcached 報錯的鍵,那么其他內(nèi)置的緩存框架會發(fā)出警告?django.core.cache.backends.base.CacheKeyWarning
?
如果你正在使用的生產(chǎn)后端能接受更大范圍的鍵(自定義后端或非 memcached 的內(nèi)置后端),并且在沒有警告的情況下使用更廣的范圍,你可以在 ?INSTALLED_APPS
?中的 management 模塊里靜默 ?CacheKeyWarning
?使用這個代碼:
import warnings
from django.core.cache import CacheKeyWarning
warnings.simplefilter("ignore", CacheKeyWarning)
如果你想為某個內(nèi)置的后端提供自定義的鍵檢驗邏輯,你可以將其子類化,只覆蓋 ?validate_key
?方法,并且按照 使用自定義緩存后端 的說明操作。比如,想要為 locmem 后端執(zhí)行此操作,請將下面代碼放入模塊中:
from django.core.cache.backends.locmem import LocMemCache
class CustomLocMemCache(LocMemCache):
def validate_key(self, key):
"""Custom validation, raising exceptions or warnings as needed."""
...
然后在 ?CACHES
?里的 ?BACKEND
?部分使用路徑導入此類。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: