from django.db import models from django.db.models import signals from django.core.files.base import ContentFile from django.db.models.fields.files import ImageFieldFile import cStringIO as StringIO import Image import os class DefaultImageFieldFile(ImageFieldFile): def __init__(self, *args, **kwargs): super(DefaultImageFieldFile, self).__init__(*args, **kwargs) self.default_url = self.field.default_url def _get_url(self): try: return super(DefaultImageFieldFile, self)._get_url() except ValueError: return self.default_url url = property(_get_url) class AutoImageField(models.ImageField): attr_class = DefaultImageFieldFile def __init__(self, *args, **kwargs): self.prepopulate_from = kwargs.pop('prepopulate_from', None) if self.prepopulate_from: self.size = kwargs.pop('size') self.default_url = kwargs.pop('default', None) if self.prepopulate_from or self.default_url: kwargs['blank'] = True super(AutoImageField, self).__init__(*args, **kwargs) def _downsize_image(self, instance, name, width, height): src = getattr(instance, self.prepopulate_from) img = Image.open(src.path) img = img.convert("RGB") img.thumbnail((width, height), Image.ANTIALIAS) io = StringIO.StringIO() img.save(io, 'JPEG') fname = os.path.split(src.path)[-1].split('.') fname.pop() fname[-1] = fname[-1] + name fname.append('jpg') fname = '.'.join(fname) return ContentFile(io.getvalue()), fname def contribute_to_class(self, cls, name): super(AutoImageField, self).contribute_to_class(cls, name) def process_image(instance, **kwargs): if not getattr(instance, name, False) and getattr(instance, self.prepopulate_from, False): width, height = self.size img, fname = self._downsize_image(instance, name, width, height) getattr(instance, name).save(fname, img, False) if self.prepopulate_from: signals.pre_save.connect(process_image, sender=cls, weak=False)