def stdimg(instance, image, thumbnail, force_size=False): ''' standarization of image fields (for being used when saving models) automatically creates thumbnail change image name to /path/to/images/-. resize image to specified size arguments: instance: model instance to be saved image: tuple containing image field name, and desired size (a tuple containing width and height) thumbnail: tuple containing thumbnail field name, and desired size (a tuple containing width and height) example: class MyModel(models.Model): my_image = models.ImageField(upload_to='path/to/images') my_thumbnail = models.ImageField(upload_to='path/to/thumbnails', editable=False) def save(self): super(MyClass, self).save() # We force to save and create an object id to use in image name stdimg(self, ('my_image', (640, 480)), ('my_thumbnail', (100, 75))) super(MyClass, self).save() # We update paths on db ''' import os from django.conf import settings from PIL import Image src = eval('instance.get_%s_filename()' % image[0]) if src: ext = os.path.splitext(src)[1].lower().replace('jpg', 'jpeg') filename = lambda s: instance._meta.get_field(s).get_filename('%s-%s%s' % (s, instance.id, ext)) for field in (image, thumbnail): img = Image.open(src) if force_size: size = field[1] ratio = lambda t: float(t[1]) / float(t[0]) if ratio(size) > ratio(img.size): x, y = float(img.size[0]) / img.size[1] * size[1], size[1] pos_x, pos_y = float(x - size[0]) / 2, 0 else: x, y = size[0], float(img.size[1]) / img.size[0] * size[0] pos_x, pos_y = 0, float(y - size[1]) / 2 img = img.resize((x,y), Image.ANTIALIAS) img = img.crop((pos_x, pos_y, pos_x + size[0], pos_y + size[1])) else: img.thumbnail(field[1], Image.ANTIALIAS) img.save(settings.MEDIA_ROOT + filename(field[0])) setattr(instance, field[0], filename(field[0])) if os.path.exists(src) and src != settings.MEDIA_ROOT + filename(image[0]): os.remove(src)