mirror of https://github.com/django/django.git
Fixed #12982 -- Added a get_or_set() method to the BaseCache backend.
This commit is contained in:
parent
a52cd407b8
commit
34fb909180
|
@ -147,6 +147,27 @@ class BaseCache(object):
|
||||||
d[k] = val
|
d[k] = val
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def get_or_set(self, key, default=None, timeout=DEFAULT_TIMEOUT, version=None):
|
||||||
|
"""
|
||||||
|
Fetch a given key from the cache. If the key does not exist,
|
||||||
|
the key is added and set to the default value. The default value can
|
||||||
|
also be any callable. If timeout is given, that timeout will be used
|
||||||
|
for the key; otherwise the default cache timeout will be used.
|
||||||
|
|
||||||
|
Returns the value of the key stored or retrieved on success,
|
||||||
|
False on error.
|
||||||
|
"""
|
||||||
|
if default is None:
|
||||||
|
raise ValueError('You need to specify a value.')
|
||||||
|
val = self.get(key, version=version)
|
||||||
|
if val is None:
|
||||||
|
if callable(default):
|
||||||
|
default = default()
|
||||||
|
val = self.add(key, default, timeout=timeout, version=version)
|
||||||
|
if val:
|
||||||
|
return self.get(key, version=version)
|
||||||
|
return val
|
||||||
|
|
||||||
def has_key(self, key, version=None):
|
def has_key(self, key, version=None):
|
||||||
"""
|
"""
|
||||||
Returns True if the key is in the cache and has not expired.
|
Returns True if the key is in the cache and has not expired.
|
||||||
|
|
|
@ -94,7 +94,8 @@ Minor features
|
||||||
Cache
|
Cache
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
||||||
* ...
|
* ``django.core.cache.backends.base.BaseCache`` now has a ``get_or_set()``
|
||||||
|
method.
|
||||||
|
|
||||||
Email
|
Email
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
|
@ -778,6 +778,25 @@ If you need to know whether ``add()`` stored a value in the cache, you can
|
||||||
check the return value. It will return ``True`` if the value was stored,
|
check the return value. It will return ``True`` if the value was stored,
|
||||||
``False`` otherwise.
|
``False`` otherwise.
|
||||||
|
|
||||||
|
If you want to get a key's value or set a value if the key isn't in the cache,
|
||||||
|
there is the ``get_or_set()`` method. It takes the same parameters as ``get()``
|
||||||
|
but the default is set as the new cache value for that key, rather than simply
|
||||||
|
returned::
|
||||||
|
|
||||||
|
>>> cache.get('my_new_key') # returns None
|
||||||
|
>>> cache.get_or_set('my_new_key', 'my new value', 100)
|
||||||
|
'my new value'
|
||||||
|
|
||||||
|
You can also pass any callable as a *default* value::
|
||||||
|
|
||||||
|
>>> import datetime
|
||||||
|
>>> cache.get_or_set('some-timestamp-key', datetime.datetime.now)
|
||||||
|
datetime.datetime(2014, 12, 11, 0, 15, 49, 457920)
|
||||||
|
|
||||||
|
.. versionchanged:: 1.9
|
||||||
|
|
||||||
|
The ``get_or_set()`` method was added.
|
||||||
|
|
||||||
There's also a ``get_many()`` interface that only hits the cache once.
|
There's also a ``get_many()`` interface that only hits the cache once.
|
||||||
``get_many()`` returns a dictionary with all the keys you asked for that
|
``get_many()`` returns a dictionary with all the keys you asked for that
|
||||||
actually exist in the cache (and haven't expired)::
|
actually exist in the cache (and haven't expired)::
|
||||||
|
|
|
@ -884,6 +884,28 @@ class BaseCacheTests(object):
|
||||||
with self.assertRaises(pickle.PickleError):
|
with self.assertRaises(pickle.PickleError):
|
||||||
cache.set('unpickable', Unpickable())
|
cache.set('unpickable', Unpickable())
|
||||||
|
|
||||||
|
def test_get_or_set(self):
|
||||||
|
self.assertIsNone(cache.get('projector'))
|
||||||
|
self.assertEqual(cache.get_or_set('projector', 42), 42)
|
||||||
|
self.assertEqual(cache.get('projector'), 42)
|
||||||
|
|
||||||
|
def test_get_or_set_callable(self):
|
||||||
|
def my_callable():
|
||||||
|
return 'value'
|
||||||
|
|
||||||
|
self.assertEqual(cache.get_or_set('mykey', my_callable), 'value')
|
||||||
|
|
||||||
|
def test_get_or_set_version(self):
|
||||||
|
cache.get_or_set('brian', 1979, version=2)
|
||||||
|
with self.assertRaisesMessage(ValueError, 'You need to specify a value.'):
|
||||||
|
cache.get_or_set('brian')
|
||||||
|
with self.assertRaisesMessage(ValueError, 'You need to specify a value.'):
|
||||||
|
cache.get_or_set('brian', version=1)
|
||||||
|
self.assertIsNone(cache.get('brian', version=1))
|
||||||
|
self.assertEqual(cache.get_or_set('brian', 42, version=1), 42)
|
||||||
|
self.assertEqual(cache.get_or_set('brian', 1979, version=2), 1979)
|
||||||
|
self.assertIsNone(cache.get('brian', version=3))
|
||||||
|
|
||||||
|
|
||||||
@override_settings(CACHES=caches_setting_for_tests(
|
@override_settings(CACHES=caches_setting_for_tests(
|
||||||
BACKEND='django.core.cache.backends.db.DatabaseCache',
|
BACKEND='django.core.cache.backends.db.DatabaseCache',
|
||||||
|
|
Loading…
Reference in New Issue