From 1956e16b4bebcd23018e60369889df505eeb787e Mon Sep 17 00:00:00 2001 From: Matthew Tretter Date: Sat, 11 Feb 2012 00:04:56 -0500 Subject: [PATCH] Only invalidate spec file if source changes --- imagekit/models.py | 53 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/imagekit/models.py b/imagekit/models.py index a742719..a6fadfb 100755 --- a/imagekit/models.py +++ b/imagekit/models.py @@ -5,7 +5,7 @@ from StringIO import StringIO from django.core.files.base import ContentFile from django.db import models from django.db.models.fields.files import ImageFieldFile -from django.db.models.signals import post_save, post_delete +from django.db.models.signals import post_init, post_save, post_delete from django.utils.encoding import force_unicode, smart_str from imagekit.utils import img_to_fobj, open_image, \ @@ -126,10 +126,12 @@ class ImageSpec(_ImageSpecMixin): # Connect to the signals only once for this class. uid = '%s.%s' % (cls.__module__, cls.__name__) - post_save.connect(_post_save_handler, sender=cls, - dispatch_uid='%s_save' % uid) - post_delete.connect(_post_delete_handler, sender=cls, - dispatch_uid='%s.delete' % uid) + post_init.connect(ImageSpec._post_init_receiver, sender=cls, + dispatch_uid=uid) + post_save.connect(ImageSpec._post_save_receiver, sender=cls, + dispatch_uid=uid) + post_delete.connect(ImageSpec._post_delete_receiver, sender=cls, + dispatch_uid=uid) # Register the field with the cache_state_backend try: @@ -137,6 +139,36 @@ class ImageSpec(_ImageSpecMixin): except AttributeError: pass + @staticmethod + def _post_save_receiver(sender, instance=None, created=False, raw=False, **kwargs): + if not raw: + old_hashes = instance._ik._source_hashes.copy() + new_hashes = ImageSpec._update_source_hashes(instance) + for attname in instance._ik.spec_fields: + if old_hashes[attname] != new_hashes[attname]: + getattr(instance, attname).invalidate() + + @staticmethod + def _update_source_hashes(instance): + """ + Stores hashes of the source image files so that they can be compared + later to see whether the source image has changed (and therefore whether + the spec file needs to be regenerated). + + """ + instance._ik._source_hashes = dict((f.attname, hash(f.source_file)) \ + for f in instance._ik.spec_files) + return instance._ik._source_hashes + + @staticmethod + def _post_delete_receiver(sender, instance=None, **kwargs): + for spec_file in instance._ik.spec_files: + spec_file.clear() + + @staticmethod + def _post_init_receiver(sender, instance, **kwargs): + ImageSpec._update_source_hashes(instance) + def _get_suggested_extension(name, format): original_extension = os.path.splitext(name)[1] @@ -366,17 +398,6 @@ class _ImageSpecDescriptor(object): return img_spec_file -def _post_save_handler(sender, instance=None, created=False, raw=False, **kwargs): - if not raw: - for spec_file in instance._ik.spec_files: - spec_file.invalidate() - - -def _post_delete_handler(sender, instance=None, **kwargs): - for spec_file in instance._ik.spec_files: - spec_file.clear() - - class ProcessedImageFieldFile(ImageFieldFile, _ImageSpecFileMixin): def save(self, name, content, save=True): new_filename = self.field.generate_filename(self.instance, name)