From 8a2738ca8ad28ed11cae842f1dec48da86a0a985 Mon Sep 17 00:00:00 2001 From: Matthew Tretter Date: Thu, 6 Sep 2012 00:07:40 -0400 Subject: [PATCH] Add backend for caching image state --- imagekit/conf.py | 2 ++ imagekit/generators.py | 16 +++++---- imagekit/imagecache/backends/base.py | 49 +++++++++++++++++++++++++--- imagekit/models/fields/files.py | 3 ++ 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/imagekit/conf.py b/imagekit/conf.py index 5618bcb..6c09232 100644 --- a/imagekit/conf.py +++ b/imagekit/conf.py @@ -3,5 +3,7 @@ from appconf import AppConf class ImageKitConf(AppConf): DEFAULT_IMAGE_CACHE_BACKEND = 'imagekit.imagecache.backends.Simple' + CACHE_BACKEND = None VALIDATE_ON_ACCESS = True CACHE_DIR = 'CACHE/images' + CACHE_PREFIX = 'ik-' diff --git a/imagekit/generators.py b/imagekit/generators.py index 344fc67..6c4a974 100644 --- a/imagekit/generators.py +++ b/imagekit/generators.py @@ -49,18 +49,20 @@ class SpecFileGenerator(object): content = IKContentFile(filename, imgfile.read(), format=format) return img, content + def get_hash(self, source_file): + return md5(''.join([ + pickle.dumps(self.get_processors(source_file)), + self.format, + pickle.dumps(self.options), + str(self.autoconvert), + ])).hexdigest() + def generate_filename(self, source_file): source_filename = source_file.name filename = None if source_filename: - hash = md5(''.join([ - pickle.dumps(self.get_processors(source_file)), - self.format, - pickle.dumps(self.options), - str(self.autoconvert), - ])).hexdigest() + hash = self.get_hash(source_file) extension = suggest_extension(source_filename, self.format) - filename = os.path.normpath(os.path.join( settings.IMAGEKIT_CACHE_DIR, os.path.splitext(source_filename)[0], diff --git a/imagekit/imagecache/backends/base.py b/imagekit/imagecache/backends/base.py index 91a319f..a489f6d 100644 --- a/imagekit/imagecache/backends/base.py +++ b/imagekit/imagecache/backends/base.py @@ -1,4 +1,6 @@ from ...utils import get_singleton +from django.core.cache import get_cache +from django.core.cache.backends.dummy import DummyCache from django.core.exceptions import ImproperlyConfigured @@ -16,7 +18,39 @@ class InvalidImageCacheBackendError(ImproperlyConfigured): pass -class Simple(object): +class CachedValidationBackend(object): + @property + def cache(self): + if not getattr(self, '_cache', None): + from django.conf import settings + alias = settings.IMAGEKIT_CACHE_BACKEND + self._cache = get_cache(alias) if alias else DummyCache(None, {}) + return self._cache + + def get_key(self, file): + from django.conf import settings + return '%s%s-valid' % (settings.IMAGEKIT_CACHE_PREFIX, file.get_hash()) + + def is_invalid(self, file): + key = self.get_key(file) + cached_value = self.cache.get(key) + if cached_value is None: + cached_value = self._is_invalid(file) + self.cache.set(key, cached_value) + return cached_value + + def validate(self, file): + if self.is_invalid(file): + self._validate(file) + self.cache.set(self.get_key(file), True) + + def invalidate(self, file): + if not self.is_invalid(file): + self._invalidate(file) + self.cache.set(self.get_key(file), False) + + +class Simple(CachedValidationBackend): """ The most basic image cache backend. Files are considered valid if they exist. To invalidate a file, it's deleted; to validate one, it's generated @@ -24,21 +58,26 @@ class Simple(object): """ - def is_invalid(self, file): + def _is_invalid(self, file): if not getattr(file, '_file', None): # No file on object. Have to check storage. return not file.storage.exists(file.name) return False - def validate(self, file): + def _validate(self, file): """ Generates a new image by running the processors on the source file. """ - if self.is_invalid(file): - file.generate(save=True) + file.generate(save=True) def invalidate(self, file): + """ + Invalidate the file by deleting it. We override ``invalidate()`` + instead of ``_invalidate()`` because we don't really care to check + whether the file is invalid or not. + + """ file.delete(save=False) def clear(self, file): diff --git a/imagekit/models/fields/files.py b/imagekit/models/fields/files.py index b46d813..687295f 100644 --- a/imagekit/models/fields/files.py +++ b/imagekit/models/fields/files.py @@ -6,6 +6,9 @@ class ImageSpecFieldFile(ImageFieldFile): super(ImageSpecFieldFile, self).__init__(instance, field, None) self.attname = attname + def get_hash(self): + return self.field.generator.get_hash(self.source_file) + @property def source_file(self): field_name = getattr(self.field, 'image_field', None)