from django.utils.functional import curry import Image import os class ThumbnailMixIn(object): def add_accessor_methods(self, *args, **kwargs): for size in self.image_sizes: setattr(self, 'get_%s_image_url' % size, curry(self._get_SIZE_image_url, size=size)) def _get_SIZE_image_url(self, size): return self.get_image_url(size) def create_thumbnails(self): for size in self.image_sizes: self.create_thumbnail(size) def delete_thumbnails(self): try: for size in self.image_sizes: os.remove(self.get_image_path(size)) except: pass def create_thumbnail(self, size): image_size = self.image_sizes.get(size) img = Image.open(self.image.path) img.thumbnail(( image_size.get('width'), image_size.get('height') ), Image.ANTIALIAS) img.save(self.get_image_path(size)) def get_image_path(self, size): return os.sep.join([ os.path.dirname(self.image.path), self.get_image_filename(size) ]) def get_image_url(self, size): return '/'.join([ os.path.dirname(self.image.url), self.get_image_filename(size) ]) def get_image_filename(self,size): return '_'.join([size,os.path.basename(self.image.path)]) def admin_thumbnail(self): if self.image_sizes.has_key('admin'): return '' % (self.get_image_url('admin')) return ' ' admin_thumbnail.allow_tags = True # The model class Photo(models.Model, ThumbnailMixIn): title = models.CharField(max_length=200) image = models.ImageField(upload_to='photos') # Must be named image. image_sizes = { 'admin': {'width': 50, 'height': 50}, 'small': {'width': 300, 'height': 300}, 'medium': {'width': 500, 'height': 500} } # Signals def add_accessor_methods(sender, instance, signal, *args, **kwargs): if hasattr(instance, 'add_accessor_methods'): instance.add_accessor_methods() def create_thumbnails(sender, instance, signal, *args, **kwargs): if hasattr(sender, 'create_thumbnails'): sender.create_thumbnails(instance) def delete_thumbnails(sender, instance, signal, *args, **kwargs): if hasattr(sender, 'delete_thumbnails'): sender.delete_thumbnails(instance) post_init.connect(add_accessor_methods) post_save.connect(create_thumbnails, sender=Photo) post_delete.connect(delete_thumbnails, sender=Photo)