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