summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCurtis <curtis@tinbrain.net>2014-05-24 20:29:31 +1000
committerTim Graham <timograham@gmail.com>2014-07-01 06:32:53 -0400
commit71461b14ab0c5a3801d85738fde3aedd407d7115 (patch)
tree7bfb432215d6f7a0293bb50b0f8d36e7c7341e4f
parent34ba86706f0db33d9a0ab44e4abb78703e7262a9 (diff)
Fixed #22691 -- Added aliasing to cached_property.
-rw-r--r--django/utils/functional.py8
-rw-r--r--docs/ref/utils.txt20
-rw-r--r--tests/utils_tests/test_functional.py9
3 files changed, 34 insertions, 3 deletions
diff --git a/django/utils/functional.py b/django/utils/functional.py
index 361b0f14fb..c512084c6e 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -45,14 +45,18 @@ class cached_property(object):
"""
Decorator that converts a method with a single self argument into a
property cached on the instance.
+
+ Optional ``name`` argument allows you to make cached properties of other
+ methods. (e.g. url = cached_property(get_absolute_url, name='url') )
"""
- def __init__(self, func):
+ def __init__(self, func, name=None):
self.func = func
+ self.name = name or func.__name__
def __get__(self, instance, type=None):
if instance is None:
return self
- res = instance.__dict__[self.func.__name__] = self.func(instance)
+ res = instance.__dict__[self.name] = self.func(instance)
return res
diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
index 883c388a78..826dd9c7f8 100644
--- a/docs/ref/utils.txt
+++ b/docs/ref/utils.txt
@@ -423,7 +423,7 @@ Atom1Feed
.. module:: django.utils.functional
:synopsis: Functional programming tools.
-.. class:: cached_property(object)
+.. class:: cached_property(object, name)
The ``@cached_property`` decorator caches the result of a method with a
single ``self`` argument as a property. The cached result will persist
@@ -483,6 +483,24 @@ Atom1Feed
database by some other process in the brief interval between subsequent
invocations of a method on the same instance.
+ .. versionadded:: 1.8
+
+ You can use the ``name`` argument to make cached properties of other
+ methods. For example, if you had an expensive ``get_friends()`` method and
+ wanted to allow calling it without retrieving the cached value, you could
+ write::
+
+ friends = cached_property(get_friends, name='friends')
+
+ While ``person.get_friends()`` will recompute the friends on each call, the
+ value of the cached property will persist until you delete it as described
+ above::
+
+ x = person.friends # calls first time
+ y = person.get_friends() # calls again
+ z = person.friends # does not call
+ x is z # is True
+
.. function:: allow_lazy(func, *resultclasses)
Django offers many utility functions (particularly in ``django.utils``)
diff --git a/tests/utils_tests/test_functional.py b/tests/utils_tests/test_functional.py
index b6145ff0d0..e9010b3135 100644
--- a/tests/utils_tests/test_functional.py
+++ b/tests/utils_tests/test_functional.py
@@ -52,6 +52,11 @@ class FunctionalTestCase(unittest.TestCase):
def value(self):
return 1, object()
+ def other_value(self):
+ return 1
+
+ other = cached_property(other_value, name='other')
+
a = A()
# check that it is cached
@@ -67,6 +72,10 @@ class FunctionalTestCase(unittest.TestCase):
# check that it behaves like a property when there's no instance
self.assertIsInstance(A.value, cached_property)
+ # check that overriding name works
+ self.assertEqual(a.other, 1)
+ self.assertTrue(callable(a.other_value))
+
def test_lazy_equality(self):
"""
Tests that == and != work correctly for Promises.