瀏覽代碼

Fixed DjangoUnicodeDecodeError when saving pickled data to django's memcached cache backend.

Jonatan Heyman 15 年之前
父節點
當前提交
378f038a5d
共有 1 個文件被更改,包括 31 次插入1 次删除
  1. 31 1
      celery/backends/cache.py

+ 31 - 1
celery/backends/cache.py

@@ -1,7 +1,37 @@
 """celery.backends.cache"""
 from django.core.cache import cache
+from django.core.cache.backends.base import InvalidCacheBackendError
+from django.utils.encoding import smart_str
 from celery.backends.base import KeyValueStoreBackend
 
+class DjangoMemcacheWrapper(object):
+    """
+    Wrapper class to django's memcache backend class, that overrides the get method in
+    order to remove the forcing of unicode strings since it may cause binary or pickled data
+    to break.
+    """
+    def __init__(self, cache):
+        self.cache = cache
+    
+    def get(self, key, default=None):
+        val = self.cache._cache.get(smart_str(key))
+        if val is None:
+            return default
+        else:
+            return val
+    
+    def set(self, key, value, timeout=0):
+        self.cache.set(key, value, timeout)
+
+# Check if django is using memcache as the cache backend. If so, wrap the cache object in
+# our DjangoMemcacheWrapper that fixes a bug with retrieving pickled data
+try:
+    from django.core.cache.backends.memcached import CacheClass
+    if isinstance(cache, CacheClass):
+        cache = DjangoMemcacheWrapper(cache)
+except InvalidCacheBackendError:
+    pass
+
 
 class Backend(KeyValueStoreBackend):
     """Backend using the Django cache framework to store task metadata."""
@@ -10,4 +40,4 @@ class Backend(KeyValueStoreBackend):
         return cache.get(key)
 
     def set(self, key, value):
-        cache.set(key, value)
+        cache.set(key, value)