OLD | NEW |
(Empty) | |
| 1 """ |
| 2 Caching framework. |
| 3 |
| 4 This package defines set of cache backends that all conform to a simple API. |
| 5 In a nutshell, a cache is a set of values -- which can be any object that |
| 6 may be pickled -- identified by string keys. For the complete API, see |
| 7 the abstract BaseCache class in django.core.cache.backends.base. |
| 8 |
| 9 Client code should use the `cache` variable defined here to access the default |
| 10 cache backend and look up non-default cache backends in the `caches` dict-like |
| 11 object. |
| 12 |
| 13 See docs/topics/cache.txt for information on the public API. |
| 14 """ |
| 15 from threading import local |
| 16 |
| 17 from django.conf import settings |
| 18 from django.core import signals |
| 19 from django.core.cache.backends.base import ( |
| 20 BaseCache, CacheKeyWarning, InvalidCacheBackendError, |
| 21 ) |
| 22 from django.utils.module_loading import import_string |
| 23 |
| 24 __all__ = [ |
| 25 'cache', 'DEFAULT_CACHE_ALIAS', 'InvalidCacheBackendError', |
| 26 'CacheKeyWarning', 'BaseCache', |
| 27 ] |
| 28 |
| 29 DEFAULT_CACHE_ALIAS = 'default' |
| 30 |
| 31 |
| 32 def _create_cache(backend, **kwargs): |
| 33 try: |
| 34 # Try to get the CACHES entry for the given backend name first |
| 35 try: |
| 36 conf = settings.CACHES[backend] |
| 37 except KeyError: |
| 38 try: |
| 39 # Trying to import the given backend, in case it's a dotted path |
| 40 import_string(backend) |
| 41 except ImportError as e: |
| 42 raise InvalidCacheBackendError("Could not find backend '%s': %s"
% ( |
| 43 backend, e)) |
| 44 location = kwargs.pop('LOCATION', '') |
| 45 params = kwargs |
| 46 else: |
| 47 params = conf.copy() |
| 48 params.update(kwargs) |
| 49 backend = params.pop('BACKEND') |
| 50 location = params.pop('LOCATION', '') |
| 51 backend_cls = import_string(backend) |
| 52 except ImportError as e: |
| 53 raise InvalidCacheBackendError( |
| 54 "Could not find backend '%s': %s" % (backend, e)) |
| 55 return backend_cls(location, params) |
| 56 |
| 57 |
| 58 class CacheHandler(object): |
| 59 """ |
| 60 A Cache Handler to manage access to Cache instances. |
| 61 |
| 62 Ensures only one instance of each alias exists per thread. |
| 63 """ |
| 64 def __init__(self): |
| 65 self._caches = local() |
| 66 |
| 67 def __getitem__(self, alias): |
| 68 try: |
| 69 return self._caches.caches[alias] |
| 70 except AttributeError: |
| 71 self._caches.caches = {} |
| 72 except KeyError: |
| 73 pass |
| 74 |
| 75 if alias not in settings.CACHES: |
| 76 raise InvalidCacheBackendError( |
| 77 "Could not find config for '%s' in settings.CACHES" % alias |
| 78 ) |
| 79 |
| 80 cache = _create_cache(alias) |
| 81 self._caches.caches[alias] = cache |
| 82 return cache |
| 83 |
| 84 def all(self): |
| 85 return getattr(self._caches, 'caches', {}).values() |
| 86 |
| 87 |
| 88 caches = CacheHandler() |
| 89 |
| 90 |
| 91 class DefaultCacheProxy(object): |
| 92 """ |
| 93 Proxy access to the default Cache object's attributes. |
| 94 |
| 95 This allows the legacy `cache` object to be thread-safe using the new |
| 96 ``caches`` API. |
| 97 """ |
| 98 def __getattr__(self, name): |
| 99 return getattr(caches[DEFAULT_CACHE_ALIAS], name) |
| 100 |
| 101 def __setattr__(self, name, value): |
| 102 return setattr(caches[DEFAULT_CACHE_ALIAS], name, value) |
| 103 |
| 104 def __delattr__(self, name): |
| 105 return delattr(caches[DEFAULT_CACHE_ALIAS], name) |
| 106 |
| 107 def __contains__(self, key): |
| 108 return key in caches[DEFAULT_CACHE_ALIAS] |
| 109 |
| 110 def __eq__(self, other): |
| 111 return caches[DEFAULT_CACHE_ALIAS] == other |
| 112 |
| 113 def __ne__(self, other): |
| 114 return caches[DEFAULT_CACHE_ALIAS] != other |
| 115 |
| 116 |
| 117 cache = DefaultCacheProxy() |
| 118 |
| 119 |
| 120 def close_caches(**kwargs): |
| 121 # Some caches -- python-memcached in particular -- need to do a cleanup at t
he |
| 122 # end of a request cycle. If not implemented in a particular backend |
| 123 # cache.close is a no-op |
| 124 for cache in caches.all(): |
| 125 cache.close() |
| 126 |
| 127 |
| 128 signals.request_finished.connect(close_caches) |
OLD | NEW |