diff options
| author | Russell Keith-Magee <russell@keith-magee.com> | 2010-12-21 15:19:19 +0000 |
|---|---|---|
| committer | Russell Keith-Magee <russell@keith-magee.com> | 2010-12-21 15:19:19 +0000 |
| commit | 673e6fc7fb243ed44841b9969d26a161c25733b3 (patch) | |
| tree | 01bb413490cf72d003d6a31b3938686b84476fb8 /django/core/cache/__init__.py | |
| parent | 3cf8502d35cdfbb4f868a848b1f38dcc275f6be1 (diff) | |
Fixed #11675 -- Added support for the PyLibMC cache library. In order to support this, and clean up some other 1.3 caching additions, this patch also includes some changes to the way caches are defined. This means you can now have multiple caches, in the same way you have multiple databases. A huge thanks to Jacob Burch for the work on the PyLibMC backend, and to Jannis for his work on the cache definition changes.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@15005 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/core/cache/__init__.py')
| -rw-r--r-- | django/core/cache/__init__.py | 124 |
1 files changed, 100 insertions, 24 deletions
diff --git a/django/core/cache/__init__.py b/django/core/cache/__init__.py index d26eabd0c3..4cc742dedf 100644 --- a/django/core/cache/__init__.py +++ b/django/core/cache/__init__.py @@ -12,8 +12,13 @@ get_cache() function made available here. get_cache() takes a backend URI (e.g. "memcached://127.0.0.1:11211/") and returns an instance of a backend cache class. -See docs/cache.txt for information on the public API. +See docs/topics/cache.txt for information on the public API. """ +from django.conf import settings +from django.core import signals +from django.core.cache.backends.base import ( + InvalidCacheBackendError, CacheKeyWarning, BaseCache) +from django.utils import importlib try: # The mod_python version is more efficient, so try importing it first. @@ -27,10 +32,9 @@ except ImportError: # PendingDeprecationWarning from cgi import parse_qsl -from django.conf import settings -from django.core import signals -from django.core.cache.backends.base import InvalidCacheBackendError, CacheKeyWarning -from django.utils import importlib +__all__ = [ + 'get_cache', 'cache', 'DEFAULT_CACHE_ALIAS' +] # Name for use in settings file --> name of module in "backends" directory. # Any backend scheme that is not in this dictionary is treated as a Python @@ -43,6 +47,8 @@ BACKENDS = { 'dummy': 'dummy', } +DEFAULT_CACHE_ALIAS = 'default' + def parse_backend_uri(backend_uri): """ Converts the "backend_uri" into a cache scheme ('db', 'memcached', etc), a @@ -67,32 +73,102 @@ def parse_backend_uri(backend_uri): return scheme, host, params -def get_cache(backend_uri, key_prefix=None, version=None, key_func=None): - if key_prefix is None: - key_prefix = settings.CACHE_KEY_PREFIX - if version is None: - version = settings.CACHE_VERSION - if key_func is None: - key_func = settings.CACHE_KEY_FUNCTION +if not settings.CACHES: + import warnings + warnings.warn( + "settings.CACHE_* is deprecated; use settings.CACHES instead.", + PendingDeprecationWarning + ) + # Mapping for new-style cache backend api + backend_classes = { + 'memcached': 'memcached.CacheClass', + 'locmem': 'locmem.LocMemCache', + 'file': 'filebased.FileBasedCache', + 'db': 'db.DatabaseCache', + 'dummy': 'dummy.DummyCache', + } + engine, host, params = parse_backend_uri(settings.CACHE_BACKEND) + if engine in backend_classes: + engine = 'django.core.cache.backends.%s' % backend_classes[engine] + defaults = { + 'BACKEND': engine, + 'LOCATION': host, + } + defaults.update(params) + settings.CACHES[DEFAULT_CACHE_ALIAS] = defaults - if key_func is not None and not callable(key_func): - key_func_module_path, key_func_name = key_func.rsplit('.', 1) - key_func_module = importlib.import_module(key_func_module_path) - key_func = getattr(key_func_module, key_func_name) +if DEFAULT_CACHE_ALIAS not in settings.CACHES: + raise ImproperlyConfigured("You must define a '%s' cache" % DEFAULT_CACHE_ALIAS) - scheme, host, params = parse_backend_uri(backend_uri) - if scheme in BACKENDS: - name = 'django.core.cache.backends.%s' % BACKENDS[scheme] +def parse_backend_conf(backend, **kwargs): + """ + Helper function to parse the backend configuration + that doesn't use the URI notation. + """ + # Try to get the CACHES entry for the given backend name first + conf = settings.CACHES.get(backend, None) + if conf is not None: + args = conf.copy() + backend = args.pop('BACKEND') + location = args.pop('LOCATION', '') + return backend, location, args else: - name = scheme - module = importlib.import_module(name) - return module.CacheClass(host, params, key_prefix=key_prefix, version=version, key_func=key_func) + # Trying to import the given backend, in case it's a dotted path + mod_path, cls_name = backend.rsplit('.', 1) + try: + mod = importlib.import_module(mod_path) + backend_cls = getattr(mod, cls_name) + except (AttributeError, ImportError): + raise InvalidCacheBackendError("Could not find backend '%s'" % backend) + location = kwargs.pop('LOCATION', '') + return backend, location, kwargs + raise InvalidCacheBackendError( + "Couldn't find a cache backend named '%s'" % backend) + +def get_cache(backend, **kwargs): + """ + Function to load a cache backend dynamically. This is flexible by design + to allow different use cases: -cache = get_cache(settings.CACHE_BACKEND) + To load a backend with the old URI-based notation:: + + cache = get_cache('locmem://') + + To load a backend that is pre-defined in the settings:: + + cache = get_cache('default') + + To load a backend with its dotted import path, + including arbitrary options:: + + cache = get_cache('django.core.cache.backends.memcached.MemcachedCache', **{ + 'LOCATION': '127.0.0.1:11211', 'TIMEOUT': 30, + }) + + """ + try: + if '://' in backend: + # for backwards compatibility + backend, location, params = parse_backend_uri(backend) + if backend in BACKENDS: + backend = 'django.core.cache.backends.%s' % BACKENDS[backend] + params.update(kwargs) + mod = importlib.import_module(backend) + backend_cls = mod.CacheClass + else: + backend, location, params = parse_backend_conf(backend, **kwargs) + mod_path, cls_name = backend.rsplit('.', 1) + mod = importlib.import_module(mod_path) + backend_cls = getattr(mod, cls_name) + except (AttributeError, ImportError), e: + raise InvalidCacheBackendError( + "Could not find backend '%s': %s" % (backend, e)) + return backend_cls(location, params) + +cache = get_cache(DEFAULT_CACHE_ALIAS) # Some caches -- python-memcached in particular -- need to do a cleanup at the # end of a request cycle. If the cache provides a close() method, wire it up # here. if hasattr(cache, 'close'): signals.request_finished.connect(cache.close) - |
