新聞中心
有時(shí),緩存整個(gè)渲染頁面并不會(huì)帶來太多好處,事實(shí)上,這樣會(huì)很不方便。

或許,你的站點(diǎn)包含了一個(gè)視圖,它的結(jié)果依賴于許多費(fèi)時(shí)的查詢,而且結(jié)果會(huì)隨著時(shí)間變化而改變。在這個(gè)情況下,使用站點(diǎn)或視圖緩存策略提供的全頁面緩存并不理想,因?yàn)椴荒芫彺嫠薪Y(jié)果(一些數(shù)據(jù)經(jīng)常變動(dòng)),不過你仍然可以緩存幾乎沒有變化的結(jié)果。
像這樣的情況,Django 公開了一個(gè)底層的緩存 API 。你可以使用這個(gè) API 以任意級(jí)別粒度在緩存中存儲(chǔ)對(duì)象。你可以緩存任何可以安全的 pickle 的 Python 對(duì)象:模型對(duì)象的字符串、字典、列表,或者其他。
訪問緩存
django.core.cache.caches
你可以通過類似字典一樣的 ?object: django.core.cache.caches? 對(duì)象訪問在 ?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í)例。
django.core.cache.cache
作為快捷方式,默認(rèn)緩存可以通過 ?django.core.cache.cache? 引用:
>>> from django.core.cache import cache這個(gè)對(duì)象等價(jià)于 ?caches['default'] ?
基本用法
基本接口是:
cache.set(key, value, timeout=DEFAULT_TIMEOUT, version=None)
>>> cache.set('my_key', 'hello, world!', 30)cache.get(key, default=None, version=None)
>>> 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'cache.add(key, value, timeout=DEFAULT_TIMEOUT, version=None)
在鍵不存在的時(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'如果你想知道通過 ?add()? 存儲(chǔ)的值是否在緩存中,你可以檢查返回值。如果值已保存,將返回 ?True ?,否則返回 ?False ?。
cache.get_or_set(key, default, timeout=DEFAULT_TIMEOUT, version=None)
如果你想得到鍵值或者如果鍵不在緩存中時(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)cache.get_many(keys, version=None)
這里也有 ?get_many()? 接口,返回一個(gè)字典,其中包含你請(qǐng)求的鍵,這些鍵真實(shí)存在緩存中(并且沒過期):
>>> cache.set('a', 1)
>>> cache.set('b', 2)
>>> cache.set('c', 3)
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}cache.set_many(dict, timeout)
使用 ?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法插入的鍵列表。
cache.delete(key, version=None)
你可以使用 ?delete()? 顯式地刪除鍵,以清空特定對(duì)象的緩存:
>>> cache.delete('a')
True如果鍵被成功刪除,將返回? delete()? ,否則返回 ?False ?。
cache.delete_many(keys, version=None)
如果你想一次性清除很多鍵,給 ?delete_many()? 傳遞一個(gè)鍵列表即可刪除。
>>> cache.delete_many(['a', 'b', 'c'])cache.clear()
最后,如果你想刪除緩存里的所有鍵,使用 ?cache.clear()?。注意,?clear() ?將刪除緩存里的 任何 鍵,不只是你應(yīng)用里設(shè)置的那些鍵。
>>> cache.clear()cache.touch(key, timeout=DEFAULT_TIMEOUT, version=None)
?cache.touch()? 為鍵設(shè)置一個(gè)新的過期時(shí)間。比如,更新一個(gè)鍵為從現(xiàn)在起10秒鐘后過期:
>>> cache.touch('a', 10)
True和其他方法一樣,?timeout ?參數(shù)是可選的,并且默認(rèn)是 ?CACHES ?設(shè)置的相應(yīng)后端的 ?TIMEOUT ?選項(xiàng)。
如果鍵被成功 ?touch()?,將返回 ?True?,否則返回 ?False?。
cache.incr(key, delta=1, version=None)
cache.decr(key, delta=1, version=None)
你也可以使用分別使用 ?incr()? 或 ?decr()? 方法來遞增或遞減一個(gè)已經(jīng)存在的鍵的值。默認(rèn)情況下,存在的緩存值將遞增或遞減1。通過為遞增/遞減的調(diào)用提供參數(shù)來指定其他遞增/遞減值。如果你試圖遞增或遞減一個(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)
6cache.close()
如果緩存后端已經(jīng)實(shí)現(xiàn)了 ?close()? 方法,你可以關(guān)閉和緩存的連接。
>>> cache.close()緩存鍵前綴
如果你正在服務(wù)器之間或者生產(chǎn)/開發(fā)緩存之間共享緩存實(shí)例,有可能會(huì)使得一個(gè)服務(wù)器使用另一個(gè)服務(wù)器的緩存數(shù)據(jù)。如果緩存數(shù)據(jù)格式是相同的,這會(huì)導(dǎo)致一些難以診斷的問題。
為了防止這個(gè)問題,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 提供更好的方式來指向單個(gè)緩存值。Django 緩存框架有一個(gè)系統(tǒng)范圍的版本標(biāo)識(shí),需要在 ?VERSION ?緩存配置中指定。這個(gè)配置的值將自動(dòng)與緩存前綴和用戶提供的緩存鍵組合起來獲取最終的緩存鍵。
默認(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() ?方法來遞增或遞減。這使得特定鍵會(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!'緩存鍵轉(zhuǎn)換
如前面兩節(jié)所述,用戶提供的緩存鍵不是單獨(dú)使用的,它是與緩存前綴和鍵版本組合后獲取最終緩存鍵。默認(rèn)情況下,使用冒號(hào)連接這三部分生成最終的字符串:
def make_key(key, key_prefix, version):
return '%s:%s:%s' % (key_prefix, version, key)如果你想用不同方式組合,或者應(yīng)用其他處理來獲得最終鍵(比如,獲得關(guān)鍵部分的哈希摘要),那么你可以提供一個(gè)自定義的鍵函數(shù)。
?KEY_FUNCTION ?緩存設(shè)置指定一個(gè)與上面的 ?make_key()? 原型匹配的函數(shù)路徑。如果提供,這個(gè)自定義鍵函數(shù)將代替默認(rèn)的鍵組合函數(shù)來使用。
緩存鍵警告
Memcached 作為最常用的緩存后端,不允許緩存鍵超過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)置后端),并且在沒有警告的情況下使用更廣的范圍,你可以在 ?INSTALLED_APPS ?中的 management 模塊里靜默 ?CacheKeyWarning ?使用這個(gè)代碼:
import warnings
from django.core.cache import CacheKeyWarning
warnings.simplefilter("ignore", CacheKeyWarning)如果你想為某個(gè)內(nèi)置的后端提供自定義的鍵檢驗(yàn)邏輯,你可以將其子類化,只覆蓋 ?validate_key ?方法,并且按照 使用自定義緩存后端 的說明操作。比如,想要為 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)入此類。
分享文章:創(chuàng)新互聯(lián)Django4.0教程:Django4.0緩存框架-底層緩存API
文章出自:http://www.5511xx.com/article/djospeo.html


咨詢
建站咨詢
