summaryrefslogtreecommitdiff
path: root/django/core/cache/backends/base.py
diff options
context:
space:
mode:
authorNick Pope <nick.pope@flightdataservices.com>2020-12-14 10:42:22 +0000
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-12-17 09:57:21 +0100
commitbb64b99b78a579cb2f6178011a4cf9366e634438 (patch)
tree7c20092227eb3038ba7ca664112064bb16ed516a /django/core/cache/backends/base.py
parentd23dad5778b3610a5f870b4757ba628780924dd1 (diff)
Fixed #29867 -- Added support for storing None value in caches.
Many of the cache operations make use of the default argument to the .get() operation to determine whether the key was found in the cache. The default value of the default argument is None, so this results in these operations assuming that None is not stored in the cache when it actually is. Adding a sentinel object solves this issue. Unfortunately the unmaintained python-memcached library does not support a default argument to .get(), so the previous behavior is preserved for the deprecated MemcachedCache backend.
Diffstat (limited to 'django/core/cache/backends/base.py')
-rw-r--r--django/core/cache/backends/base.py30
1 files changed, 15 insertions, 15 deletions
diff --git a/django/core/cache/backends/base.py b/django/core/cache/backends/base.py
index 22b8397cac..1e2c7c9509 100644
--- a/django/core/cache/backends/base.py
+++ b/django/core/cache/backends/base.py
@@ -52,6 +52,8 @@ def get_key_func(key_func):
class BaseCache:
+ _missing_key = object()
+
def __init__(self, params):
timeout = params.get('timeout', params.get('TIMEOUT', 300))
if timeout is not None:
@@ -151,8 +153,8 @@ class BaseCache:
"""
d = {}
for k in keys:
- val = self.get(k, version=version)
- if val is not None:
+ val = self.get(k, self._missing_key, version=version)
+ if val is not self._missing_key:
d[k] = val
return d
@@ -165,31 +167,29 @@ class BaseCache:
Return the value of the key stored or retrieved.
"""
- val = self.get(key, version=version)
- if val is None:
+ val = self.get(key, self._missing_key, version=version)
+ if val is self._missing_key:
if callable(default):
default = default()
- if default is not None:
- self.add(key, default, timeout=timeout, version=version)
- # Fetch the value again to avoid a race condition if another
- # caller added a value between the first get() and the add()
- # above.
- return self.get(key, default, version=version)
+ self.add(key, default, timeout=timeout, version=version)
+ # Fetch the value again to avoid a race condition if another caller
+ # added a value between the first get() and the add() above.
+ return self.get(key, default, version=version)
return val
def has_key(self, key, version=None):
"""
Return True if the key is in the cache and has not expired.
"""
- return self.get(key, version=version) is not None
+ return self.get(key, self._missing_key, version=version) is not self._missing_key
def incr(self, key, delta=1, version=None):
"""
Add delta to value in the cache. If the key does not exist, raise a
ValueError exception.
"""
- value = self.get(key, version=version)
- if value is None:
+ value = self.get(key, self._missing_key, version=version)
+ if value is self._missing_key:
raise ValueError("Key '%s' not found" % key)
new_value = value + delta
self.set(key, new_value, version=version)
@@ -257,8 +257,8 @@ class BaseCache:
if version is None:
version = self.version
- value = self.get(key, version=version)
- if value is None:
+ value = self.get(key, self._missing_key, version=version)
+ if value is self._missing_key:
raise ValueError("Key '%s' not found" % key)
self.set(key, value, version=version + delta)