flyEn'blog

django缓存机制

单个view

1
2
3
@cache_page(60 * 15, cache="special_cache", key_prefix="site1")
def my_view(request):
...

15分钟,指定名字 ,cache_page采用可选的关键字参数key_prefix,其工作方式与中间件的CACHE_MIDDLEWARE_KEY_PREFIX设置相同。

Url

1
2
3
4
5
from django.views.decorators.cache import cache_page

urlpatterns = [
url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
]

模板

1
2
3
4
{% load cache %}
{% cache 500 sidebar request.user.username %}
.. sidebar for logged in user ..
{% endcache %}

500:时间(秒),sidebar:给缓存片段起的名称,request.user.username:指定一个以上参数来标识区分缓存片段

1
2
3
4
5
6
7
8
% load i18n %}
{% load cache %}

{% get_current_language as LANGUAGE_CODE %}

{% cache 600 welcome LANGUAGE_CODE %}
{% trans "Welcome to example.com" %}
{% endcache %}

如果USE_I18N设置为True,则每个网站中间件缓存将respect the active language。对于cache模板标记,可以使用模板中提供的translation-specific variables之一来实现相同的结果。

1
{% cache 300 local-thing ...  using="localcache" %}

默认情况下,缓存标签将尝试使用名为“template_fragments”的缓存。如果不存在这样的缓存,则它将回退到使用默认缓存。您可以选择要与using关键字参数一起使用的备用高速缓存后端,该参数必须是标记的最后一个参数。

指定未配置的缓存名称被视为错误。

底层的缓存API

1
2
3
4
5
>>> from django.core.cache import caches
>>> cache1 = caches['myalias']
>>> cache2 = caches['myalias']
>>> cache1 is cache2
True

如果key不存在,就会引发一个 InvalidCacheBackendError 。

基本用法

1
2
3
>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'

如果对象不存在于缓存中,则cache.get()返回None

1
2
3
4
# Wait 30 seconds for 'my_key' to expire...

>>> cache.get('my_key')
None

可采用default参数,如果对象不存在于缓存中,可指定返回哪个值。

1
2
>>> cache.get('my_key', 'has expired')
'has expired'

要添加键(如果它尚不存在),使用add()方法。它使用与set()相同的参数,但如果指定的键已经存在,它不会尝试更新缓存。

1
2
3
4
>>> cache.set('add_key', 'Initial value')
>>> cache.add('add_key', 'New value')
>>> cache.get('add_key')
'Initial value'

还有一个get_many()接口,只会命中一次缓存。get_many()返回一个字典,其中包含您请求的所有实际存在于缓存中的键(并且未过期)。

1
2
3
4
5
>>> 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()传递键值对的字典:

1
2
3
>>> cache.set_many({'a': 1, 'b': 2, 'c': 3})
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}

1
2
3
>>> cache.delete('a')
>>> cache.delete_many(['a', 'b', 'c']) # 清除一堆键
>>> cache.clear() # 删除缓存中的所有键

clear()将从缓存中删除所有,而不仅仅是应用程序设置的键。

使用incr()或decr()方法分别递增或递减已存在的键。

1
2
3
4
5
6
7
8
9
>>> cache.set('num', 1)
>>> cache.incr('num')
2
>>> cache.incr('num', 10)
12
>>> cache.decr('num')
11
>>> cache.decr('num', 5)
6

incr() / decr()方法不能保证是原子的。在那些支持原子递增/递减(最明显的是memcached后端)的后端,递增和递减操作将是原子的。然而,如果后端本身不提供增量/减量操作,则它将使用两步检索/更新来实现。

如果由缓存后端实现,可以使用close()关闭与缓存的连接。

1
>>> cache.close()

缓存版本控制

1
2
3
4
5
6
7
8
# 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!'

用户提供的缓存键不是逐字使用的 - 它与缓存前缀和键版本结合以提供最终缓存键。默认情况下,使用冒号连接这三个部分以生成最终字符串。

1
2
def make_key(key, key_prefix, version):
return ':'.join([key_prefix, str(version), key])

缓存关键警告
如果正使用可接受更广泛的密钥(自定义后端或非memcached内置后端之一)的生产后端,并想使用更广泛的范围而不发出警告,您可以在其中一个INSTALLED_APPS的管理模块中使用此代码静音CacheKeyWarning。

1
2
3
4
import warnings
from django.core.cache import CacheKeyWarning

warnings.simplefilter("ignore", CacheKeyWarning)

如果您要为其中一个内置后端提供自定义键验证逻辑,则可以对其进行子类化,仅覆盖validate_key方法,并按照的说明使用自定义缓存后端。
如为locmem后端执行此操作:

1
2
3
4
from django.core.cache.backends.locmem import LocMemCache

class CustomLocMemCache(LocMemCache):
def validate_key(self, key):

下游缓存
使用Vary头

Fork me on GitHub