summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2010-06-21 00:50:13 -0500
committerDan McGee <dan@archlinux.org>2010-06-21 00:50:19 -0500
commit8ba6ad8521f01e66e8712aa3894633844195ea9c (patch)
tree0dbd2077f9ef0f263121dcebdc2927d6fd422a7e
parent03ccd8ad8c81f3bf719c7904d8ab76e280b1773b (diff)
downloadarchweb-8ba6ad8521f01e66e8712aa3894633844195ea9c.tar.gz
archweb-8ba6ad8521f01e66e8712aa3894633844195ea9c.zip
Add utility cache_function
This allows caching the results of an arbitrary function and its arguments in the Django-managed cache, e.g. memcached in production. Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--main/utils.py35
1 files changed, 35 insertions, 0 deletions
diff --git a/main/utils.py b/main/utils.py
index c258c115..40010b86 100644
--- a/main/utils.py
+++ b/main/utils.py
@@ -1,2 +1,37 @@
+try:
+ import cPickle as pickle
+except ImportError:
+ import pickle
+from django.utils.hashcompat import md5_constructor
+
+def cache_function(length):
+ """
+ A variant of the snippet posted by Jeff Wheeler at
+ http://www.djangosnippets.org/snippets/109/
+
+ Caches a function, using the function and its arguments as the key, and the
+ return value as the value saved. It passes all arguments on to the
+ function, as it should.
+
+ The decorator itself takes a length argument, which is the number of
+ seconds the cache will keep the result around.
+ """
+ def decorator(func):
+ def inner_func(*args, **kwargs):
+ from django.core.cache import cache
+
+ raw = [func.__name__, func.__module__, args, kwargs]
+ pickled = pickle.dumps(raw, protocol=pickle.HIGHEST_PROTOCOL)
+ key = md5_constructor(pickled).hexdigest()
+ value = cache.get(key)
+ if value is not None:
+ return value
+ else:
+ result = func(*args, **kwargs)
+ cache.set(key, result, length)
+ return result
+ return inner_func
+ return decorator
+
#utility to make a pair of django choices
make_choice = lambda l: [(str(m), str(m)) for m in l]