Django缓存框架API
这里写自定义目录标题
- 访问缓存
- django.core.cache.caches
- django.core.cache.cache
- 基本用法
- cache.set(key, value, timeout=DEFAULT_TIMEOUT, version=None)
- cache.get(key, default=None, version=None)
- cache.add(key, value, timeout=DEFAULT_TIMEOUT, version=None)
- cache.get_or_set(key, default, timeout=DEFAULT_TIMEOUT, version=None)
- cache.get_many(keys, version=None)
- cache.set_many(dict, timeout)
- cache.delete(key, version=None)
- cache.delete_many(keys, version=None)
- cache.clear()
- cache.touch(key, timeout=DEFAULT_TIMEOUT, version=None)
- cache.incr/decr(key, delta=1, version=None)
- cache.close()
- 缓存前缀
- 缓存版本控制
- 缓存键转换
有时,缓存整个渲染页面并不会带来太多好处,事实上,这样会很不方便。比如站点包含一个视图,它的结果依赖许多费时的查询,而且结果会随着时间变化而改变。在这个情况下,使用站点或视图缓存策略提供的全页面缓存并不理想,以为不能缓存所有结果(一些数据经常变动),不过仍然可以缓存几乎没有变化的结果。
像这样的情况Django公开了一个底层的缓存API。可以使用这个API以任意级别颗粒度在缓存中存储对象。可以缓存任何可以安全的pickle的Python对象:模型对象的字符串、字典、列表或其它(大部分通用的Python对象都可以被pickle)。
访问缓存
django.core.cache.caches
可以通过类似字典一样的object:django.core.cache.caches对象访问在CACHES配置的缓存。重复请求同一个线程里的同一个别名将返回同一个对象。
from django.core.cache import caches
cache1 = caches["myalias"]
cache2 = caches["myalias"]
cache1 is cache2 # True
如果键名不存在,将会引发InvalidCacheBackendError错误。为了支持线程安全,将为每个线程返回缓存后端不同实例。
django.core.cache.cache
作为一种快捷方式,默认缓存可以通过django.core.cache.cache访问:from django.core.cache import cache
,这个对象等价于caches['default']
。
基本用法
cache.set(key, value, timeout=DEFAULT_TIMEOUT, version=None)
# 设置缓存
cache.set('my_key', 'hello, world!', 30)
key是一个字符串,value可以任何picklable形式的Python对象。
timeout参数是可选的,默认为CACHES中响应后端的timeout参数。它是值存在缓存里的秒数。timeout设置为None时将永久缓存。timeout为0将不缓存值。
cache.get(key, default=None, version=None)
cache.get('my_key') # hello, world!
如果缓存中不存在该对象,cache.get()
返回None:
# Wait 30 seconds for 'my_key' to expire...
cache.get("my_key") # None
如果需要确定对象是否存在于缓存中,并且您已经存储了字面值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
cahce.get()
可以接受一个default参数,用于指定在对象不存在于缓存中时返回的值:
cache.get("my_key", "has expired") # 'has expired'
cache.add(key, value, timeout=DEFAULT_TIMEOUT, version=None)
如果只在健不存在时才添加键,可以使用add()
方法。它接受与set()
相同的参数,但如果指定的键已存在,它不会尝试更新缓存:
cache.set("add_key", "Initial value") # True
cache.add("add_key", "New value") # False
cache.get("add_key") # 'Initial value'
如果想知道通过add()
存储的值是否存在缓存中,你可以检查返回值。如果值已保存,将返回True,否则返回False。
cache.get_or_set(key, default, timeout=DEFAULT_TIMEOUT, version=None)
如果要获取键的值,或者如果键不再缓存中则设置一个值,可以使用get_or_set()
方法。它接受与get()
相同的参数,但默认值将作为该键的新缓存值设置,而不是返回值:
cache.get("my_new_key") # returns None
cache.get_or_set("my_new_key", "my new value", 100) # 'my new value'
还可以将任何可调用对象作为default值传递:
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()
只访问缓存一次,返回一个字典,其中包含请求的实际存在于缓存中未过期的所有键:
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()
来传递一个键值对的字典:
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参数。在已支持的后端(memcached),set_many()
会返回无法插入的键列表。
cache.delete(key, version=None)
delete()
明确删除键,以清除特定对象的缓存:
cache.delete("a") # True
如果键被成功删除,将返回True,否则返回False
cache.delete_many(keys, version=None)
如果想一次性清除一组键,可以使用delete_manay()
方法,并传入要清除的键列表:
cahce.delete_many(['a', 'b', 'c']])
cache.clear()
如果想删除缓存中所有的键,可以使用cache.clear()
。注意,clear()
会从缓存中删除所有内容,不仅仅是自己应用程序设置的键:
cache.touch(key, timeout=DEFAULT_TIMEOUT, version=None)
设置键的新过期时间,例如要将键更新为在10秒后过期:
cache.touch('a', 10) # True
和其他方法一样,timeout参数是可选的,并且默认是CACHES设置的响应后端的TIMEOUT选项。
如果键被成功touch()
,将返回True,否则返回False。
cache.incr/decr(key, delta=1, version=None)
可以使用incr()或decr()方法来分别递增或递减已存在的键。默认情况下现有的缓存值将递增或递减1,通过在递增、递减调用中提供参数来指定其他递增、递减的值。如果尝试递增或递减不存在的键,则会引发ValueError:
cache.set("num", 1)
cache.incr("num") # 2
cache.incr("num", 10) # 12cache.decr("num") # 11
cache.decr("num", 5) # 6
提示:不保证incr()
、decr()
方法是原子的。那些后端支持原子递增、递减(最值得注意的时memecached后端),则递增和递减操作是原子的,然而如果后端本身没有提供递增、递减方法,则将使用检索和更新两步来实现
cache.close()
如果缓存后端已经实现了close()
方法,可以关闭缓存的连接。
对于没有实现close方法的缓存,它将无效操作。
缓存前缀
如果正在服务器之间或者生产、开发缓存之间共享缓存实例,有可能会使得一个服务器使用另一个服务器的缓存数据。如果缓存数据格式是相同的,这会导致一些难以诊断的问题。
为了防止这个问题,Django为单台服务器提供了为素有缓存键提供前缀的方法。当一个特殊的缓存键被保存或检索时,Django会为缓存自动添加KEY_PREFIX缓存设置的前缀。
要确保每个Django实例有不同的KEY_PREFIX,这样就保证缓存值不会发生冲突。
KEY_PREFIX默认’'(空字符串)。
缓存版本控制
当更改使用缓存值的运行代码时,可能需要清除任何已存在的缓存值。最简单方法是刷新整个缓存,但这会导致那些仍然有用且有效的缓存值。
Django提供更好的方式来指向单个缓存值。Django缓存框架有一个系统范围的版本标识,需要在VERSION缓存配置中指定,这个配置的值将自动与缓存前缀和用户提供的缓存键组合起来获得最终的缓存键。
默认情况下,任何键请求都会自动包含站点默认的缓存版本,但是原始缓存函数都包含一个version参数,因此可以指定要设置或获取的特定缓存键版本,例如:
# 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()
方法递增和递减特定键的版本。这使得将特定键提示到新版本,而不影响其他键。继续之前的示例:
# 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!'
缓存键转换
用户提供的缓存键不是单独使用的,它是与缓存前缀、键版本组合后获取最终缓存键。默认情况下,使用冒号连接这三部分生成最终的字符串:
def make_key(key, key_prefix, version):return "%s:%s:%s" % (key_prefix, version, key)
如果想用不同方式组合,或者应用其他处理来获得最终的键(比如,获得关键部分的哈希摘要),那么可以提供一个自定义键函数。
KEY_FUNCATION缓存设置指定一个与上面的make_key()
原型匹配的函数路径。如果提供,这个自定义键函数将替代默认的键组合函数来使用。