1
0
mirror of https://github.com/django/django.git synced 2025-05-11 09:26:29 +00:00

[1.11.x] Fixed #28601 -- Prevented cache.get_or_set() from caching None if default is a callable that returns None.

Backport of 4d60261b2a77460b4c127c3d832518b95e11a0ac from master
This commit is contained in:
Daniel Tao 2017-09-15 16:16:44 -05:00 committed by Tim Graham
parent 9b8e76f96d
commit 45b0ec87d3
3 changed files with 14 additions and 6 deletions

View File

@ -157,13 +157,15 @@ class BaseCache(object):
Return the value of the key stored or retrieved. Return the value of the key stored or retrieved.
""" """
val = self.get(key, version=version) val = self.get(key, version=version)
if val is None and default is not None: if val is None:
if callable(default): if callable(default):
default = default() default = default()
self.add(key, default, timeout=timeout, version=version) if default is not None:
# Fetch the value again to avoid a race condition if another caller self.add(key, default, timeout=timeout, version=version)
# added a value between the first get() and the add() above. # Fetch the value again to avoid a race condition if another
return self.get(key, default, version=version) # caller added a value between the first get() and the add()
# above.
return self.get(key, default, version=version)
return val return val
def has_key(self, key, version=None): def has_key(self, key, version=None):

View File

@ -9,4 +9,5 @@ Django 1.11.7 fixes several bugs in 1.11.6.
Bugfixes Bugfixes
======== ========
* ... * Prevented ``cache.get_or_set()`` from caching ``None`` if the ``default``
argument is a callable that returns ``None`` (:ticket:`28601`).

View File

@ -931,6 +931,11 @@ class BaseCacheTests(object):
self.assertEqual(cache.get_or_set('mykey', my_callable), 'value') self.assertEqual(cache.get_or_set('mykey', my_callable), 'value')
self.assertEqual(cache.get_or_set('mykey', my_callable()), 'value') self.assertEqual(cache.get_or_set('mykey', my_callable()), 'value')
def test_get_or_set_callable_returning_none(self):
self.assertIsNone(cache.get_or_set('mykey', lambda: None))
# Previous get_or_set() doesn't store None in the cache.
self.assertEqual(cache.get('mykey', 'default'), 'default')
def test_get_or_set_version(self): def test_get_or_set_version(self):
msg = ( msg = (
"get_or_set() missing 1 required positional argument: 'default'" "get_or_set() missing 1 required positional argument: 'default'"