web/lib/django/core/cache/backends/memcached.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     1 "Memcached cache backend"
     1 "Memcached cache backend"
       
     2 
       
     3 import time
     2 
     4 
     3 from django.core.cache.backends.base import BaseCache, InvalidCacheBackendError
     5 from django.core.cache.backends.base import BaseCache, InvalidCacheBackendError
     4 from django.utils.encoding import smart_unicode, smart_str
     6 from django.utils.encoding import smart_unicode, smart_str
     5 
     7 
     6 try:
     8 try:
     7     import cmemcache as memcache
     9     import cmemcache as memcache
       
    10     import warnings
       
    11     warnings.warn(
       
    12         "Support for the 'cmemcache' library has been deprecated. Please use python-memcached instead.",
       
    13         PendingDeprecationWarning
       
    14     )
     8 except ImportError:
    15 except ImportError:
     9     try:
    16     try:
    10         import memcache
    17         import memcache
    11     except:
    18     except:
    12         raise InvalidCacheBackendError("Memcached cache backend requires either the 'memcache' or 'cmemcache' library")
    19         raise InvalidCacheBackendError("Memcached cache backend requires either the 'memcache' or 'cmemcache' library")
    14 class CacheClass(BaseCache):
    21 class CacheClass(BaseCache):
    15     def __init__(self, server, params):
    22     def __init__(self, server, params):
    16         BaseCache.__init__(self, params)
    23         BaseCache.__init__(self, params)
    17         self._cache = memcache.Client(server.split(';'))
    24         self._cache = memcache.Client(server.split(';'))
    18 
    25 
       
    26     def _get_memcache_timeout(self, timeout):
       
    27         """
       
    28         Memcached deals with long (> 30 days) timeouts in a special
       
    29         way. Call this function to obtain a safe value for your timeout.
       
    30         """
       
    31         timeout = timeout or self.default_timeout
       
    32         if timeout > 2592000: # 60*60*24*30, 30 days
       
    33             # See http://code.google.com/p/memcached/wiki/FAQ
       
    34             # "You can set expire times up to 30 days in the future. After that
       
    35             # memcached interprets it as a date, and will expire the item after
       
    36             # said date. This is a simple (but obscure) mechanic."
       
    37             #
       
    38             # This means that we have to switch to absolute timestamps.
       
    39             timeout += int(time.time())
       
    40         return timeout
       
    41 
    19     def add(self, key, value, timeout=0):
    42     def add(self, key, value, timeout=0):
    20         if isinstance(value, unicode):
    43         if isinstance(value, unicode):
    21             value = value.encode('utf-8')
    44             value = value.encode('utf-8')
    22         return self._cache.add(smart_str(key), value, timeout or self.default_timeout)
    45         return self._cache.add(smart_str(key), value, self._get_memcache_timeout(timeout))
    23 
    46 
    24     def get(self, key, default=None):
    47     def get(self, key, default=None):
    25         val = self._cache.get(smart_str(key))
    48         val = self._cache.get(smart_str(key))
    26         if val is None:
    49         if val is None:
    27             return default
    50             return default
    28         else:
    51         return val
    29             if isinstance(val, basestring):
       
    30                 return smart_unicode(val)
       
    31             else:
       
    32                 return val
       
    33 
    52 
    34     def set(self, key, value, timeout=0):
    53     def set(self, key, value, timeout=0):
    35         if isinstance(value, unicode):
    54         self._cache.set(smart_str(key), value, self._get_memcache_timeout(timeout))
    36             value = value.encode('utf-8')
       
    37         self._cache.set(smart_str(key), value, timeout or self.default_timeout)
       
    38 
    55 
    39     def delete(self, key):
    56     def delete(self, key):
    40         self._cache.delete(smart_str(key))
    57         self._cache.delete(smart_str(key))
    41 
    58 
    42     def get_many(self, keys):
    59     def get_many(self, keys):
    44 
    61 
    45     def close(self, **kwargs):
    62     def close(self, **kwargs):
    46         self._cache.disconnect_all()
    63         self._cache.disconnect_all()
    47 
    64 
    48     def incr(self, key, delta=1):
    65     def incr(self, key, delta=1):
    49         return self._cache.incr(key, delta)
    66         try:
       
    67             val = self._cache.incr(key, delta)
       
    68 
       
    69         # python-memcache responds to incr on non-existent keys by
       
    70         # raising a ValueError. Cmemcache returns None. In both
       
    71         # cases, we should raise a ValueError though.
       
    72         except ValueError:
       
    73             val = None
       
    74         if val is None:
       
    75             raise ValueError("Key '%s' not found" % key)
       
    76 
       
    77         return val
    50 
    78 
    51     def decr(self, key, delta=1):
    79     def decr(self, key, delta=1):
    52         return self._cache.decr(key, delta)
    80         try:
       
    81             val = self._cache.decr(key, delta)
       
    82 
       
    83         # python-memcache responds to decr on non-existent keys by
       
    84         # raising a ValueError. Cmemcache returns None. In both
       
    85         # cases, we should raise a ValueError though.
       
    86         except ValueError:
       
    87             val = None
       
    88         if val is None:
       
    89             raise ValueError("Key '%s' not found" % key)
       
    90         return val
       
    91 
       
    92     def set_many(self, data, timeout=0):
       
    93         safe_data = {}
       
    94         for key, value in data.items():
       
    95             if isinstance(value, unicode):
       
    96                 value = value.encode('utf-8')
       
    97             safe_data[smart_str(key)] = value
       
    98         self._cache.set_multi(safe_data, self._get_memcache_timeout(timeout))
       
    99 
       
   100     def delete_many(self, keys):
       
   101         self._cache.delete_multi(map(smart_str, keys))
       
   102 
       
   103     def clear(self):
       
   104         self._cache.flush_all()