From 3ef39d9185d2b4b5377180187339c0a72039e033 Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Sat, 11 Dec 2010 16:43:31 +0100 Subject: [PATCH] Enabled database backend to properly require a cache backend that works in cross-process environments. This adds an optional setting CONSTANCE_DATABASE_CACHE_BACKEND. --- README.rst | 13 ++++++- constance/backends/database/__init__.py | 50 ++++++++++++++++++------- constance/settings.py | 3 ++ 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/README.rst b/README.rst index 1907f0e..8e65932 100644 --- a/README.rst +++ b/README.rst @@ -82,8 +82,17 @@ configuration values: pip install django-picklefield - The database backend will automatically cache the config values in memory - and clear them when when saving occurs. + The database backend has the ability to automatically cache the config + values and clear them when saving. You need to set the following setting + to enable this feature:: + + CONSTANCE_DATABASE_CACHE_BACKEND = 'memcached://127.0.0.1:11211/' + + .. note:: + + This won't work with a cache backend that doesn't support + cross-process caching, because correct cache invalidation + can't be guaranteed. .. _django-picklefield: http://pypi.python.org/pypi/django-picklefield/ diff --git a/constance/backends/database/__init__.py b/constance/backends/database/__init__.py index 2563923..6798480 100644 --- a/constance/backends/database/__init__.py +++ b/constance/backends/database/__init__.py @@ -1,37 +1,59 @@ from django.core.exceptions import ImproperlyConfigured from django.db.models.signals import post_save from django.utils.functional import memoize +from django.core.cache import get_cache +from django.core.cache.backends.locmem import CacheClass as LocMemCacheClass from constance.backends import Backend +from constance import settings -db_cache = {} +db_cache = None +if settings.DATABASE_CACHE_BACKEND: + db_cache = get_cache(settings.DATABASE_CACHE_BACKEND) + if isinstance(db_cache, LocMemCacheClass): + raise ImproperlyConfigured( + "The CONSTANCE_DATABASE_CACHE_BACKEND setting refers to a " + "subclass of Django's local-memory backend (%r). Please set " + "it to a backend that supports cross-process caching." + % settings.DATABASE_CACHE_BACKEND) class DatabaseBackend(Backend): - def __init__(self): from constance.backends.database.models import Constance - if not Constance._meta.installed: - raise ImproperlyConfigured( - "The constance.contrib.database app isn't installed correctly. " - "Make sure it's listed in the INSTALLED_APPS setting.") self._model = Constance + if not self._model._meta.installed: + raise ImproperlyConfigured( + "The constance.backends.database app isn't installed " + "correctly. Make sure it's in your INSTALLED_APPS setting.") # Clear simple cache. post_save.connect(self.clear, sender=self._model) - def _get(self, key): - try: - value = self._model._default_manager.get(key=key).value - except self._model.DoesNotExist: - return None + def mget(self, keys): + for const in self._model._default_manager.filter(key__in=keys): + yield const.key, const.value + + def get(self, key): + value = None + if db_cache: + value = db_cache.get(key) + if value is None: + try: + value = self._model._default_manager.get(key=key).value + except self._model.DoesNotExist: + pass + else: + if db_cache: + db_cache.add(key, value) return value - get = memoize(_get, db_cache, 2) def set(self, key, value): - constance, created = self._model._default_manager.get_or_create(key=key, defaults={'value': value}) + constance, created = self._model._default_manager.get_or_create( + key=key, defaults={'value': value} + ) if not created: constance.value = value constance.save() def clear(self, sender, instance, created, **kwargs): - if not created: + if db_cache and not created: db_cache.clear() diff --git a/constance/settings.py b/constance/settings.py index d046868..83e4648 100644 --- a/constance/settings.py +++ b/constance/settings.py @@ -17,3 +17,6 @@ CONNECTION_CLASS = getattr(settings, 'CONSTANCE_REDIS_CONNECTION_CLASS', REDIS_CONNECTION = getattr(settings, 'CONSTANCE_REDIS_CONNECTION', getattr(settings, 'CONSTANCE_CONNECTION', {})) + +DATABASE_CACHE_BACKEND = getattr(settings, 'CONSTANCE_DATABASE_CACHE_BACKEND', + None)