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
|
||||
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):
|
||||
"""
|
||||
Returns True if the key is in the cache and has not expired.
|
||||
|
|
|
@ -94,7 +94,8 @@ Minor features
|
|||
Cache
|
||||
^^^^^
|
||||
|
||||
* ...
|
||||
* ``django.core.cache.backends.base.BaseCache`` now has a ``get_or_set()``
|
||||
method.
|
||||
|
||||
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,
|
||||
``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.
|
||||
``get_many()`` returns a dictionary with all the keys you asked for that
|
||||
actually exist in the cache (and haven't expired)::
|
||||
|
|
|
@ -884,6 +884,28 @@ class BaseCacheTests(object):
|
|||
with self.assertRaises(pickle.PickleError):
|
||||
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(
|
||||
BACKEND='django.core.cache.backends.db.DatabaseCache',
|
||||
|
|
Loading…
Reference in New Issue