diff --git a/imagekit/specs.py b/imagekit/specs.py index 8477650..271132d 100644 --- a/imagekit/specs.py +++ b/imagekit/specs.py @@ -64,15 +64,13 @@ class ImageSpec(object): def contribute_to_class(self, cls, name): setattr(cls, name, _ImageSpecDescriptor(self, name)) - # Connect to the signals only once for this class's attribute. - uid = '%s.%s_%s' % (cls.__module__, cls.__name__, name) - post_save.connect(_create_post_save_handler(name), + # Connect to the signals only once for this class. + uid = '%s.%s' % (cls.__module__, cls.__name__) + post_save.connect(_post_save_handler, sender=cls, - weak=False, dispatch_uid='%s_save' % uid) - post_delete.connect(_create_post_delete_handler(name, uid), + post_delete.connect(_post_delete_handler, sender=cls, - weak=False, dispatch_uid='%s.delete' % uid) @@ -240,21 +238,21 @@ class _ImageSpecDescriptor(object): return BoundImageSpec(instance, self._spec, self._property_name) -def _create_post_save_handler(accessor_name): - def handler(sender, instance=None, created=False, raw=False, **kwargs): - if raw: - return - accessor = getattr(instance, accessor_name) - spec = accessor.spec - imgfield = spec._get_imgfield(instance) +def _post_save_handler(sender, instance=None, created=False, raw=False, **kwargs): + if raw: + return + bound_specs = _get_bound_specs(instance) + for bound_spec in bound_specs: + name = bound_spec.property_name + imgfield = bound_spec._get_imgfield(instance) newfile = imgfield.storage.open(str(imgfield)) img = Image.open(newfile) - img, format = spec.process(img, instance) + img, format = bound_spec.process(img, instance) if format != 'JPEG': imgfile = img_to_fobj(img, format) else: imgfile = img_to_fobj(img, format, - quality=int(spec.quality), + quality=int(bound_spec.quality), optimize=True) content = ContentFile(imgfile.read()) newfile.close() @@ -262,17 +260,24 @@ def _create_post_save_handler(accessor_name): imgfield.storage.delete(name) imgfield.storage.save(name, content) if not created: - accessor._delete() - accessor._create() - return handler + bound_spec._delete() + bound_spec._create() -def _create_post_delete_handler(accessor_name, uid): - def handler(sender, instance=None, **kwargs): - assert instance._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (instance._meta.object_name, instance._meta.pk.attname) - accessor = getattr(instance, accessor_name) - accessor._delete() - post_save.disconnect(dispatch_uid='%s_save' % uid) - post_delete.disconnect(dispatch_uid='%s.delete' % uid) +def _post_delete_handler(sender, instance=None, **kwargs): + assert instance._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (instance._meta.object_name, instance._meta.pk.attname) + bound_specs = _get_bound_specs(instance) + for bound_spec in bound_specs: + bound_spec._delete() - return handler + +def _get_bound_specs(instance): + bound_specs = [] + for key in dir(instance): + try: + value = getattr(instance, key) + except AttributeError: + continue + if isinstance(value, BoundImageSpec): + bound_specs.append(value) + return bound_specs