Django Thumbnails

May 1, 2011

Here's a simple mechanism for automatically creating thumbnails of images in Django. This is tested in Django 1.2.

Model

On the model, add a new field to hold the thumbnail. Mark it editable=False to avoid it being shown in the admin.

class ModelObject(models.Model):
    #...
    photo = models.ImageField(upload_to='images/%Y/%m', blank=True)
    thumb = models.ImageField(upload_to='images/%Y/%m', blank=True, null=True, editable=False)

In the save method on that model, call a new function to populate the thumbnail. Pass in the exiting image, thumbnail, and desired width and height

def save(self):
    self.thumb = handle_thumb(self.photo, self.thumb, 70, 70)
    super(ModelObject, self).save()

Function

The handle_thumb function creates the thumbnail if one does not already exist.

def handle_thumb(image_obj, thumb_obj, width, height):
    # create thumbnail
    if image_obj and not thumb_obj:
        thumb = str(image_obj) + ('-t%sx%s.jpg' % (width, height))
        try:
            t = Image.open(settings.MEDIA_ROOT + str(image_obj))
        except IOError:
            # image not available yet - if you save again, it'll probably work
            t = None

         if t:
            w, h = t.size
            if float(w)/h < float(width)/height:
                t = t.resize((width, h*width/w), Image.ANTIALIAS)
            else:
                t = t.resize((w*height/h, height), Image.ANTIALIAS)
            w, h = t.size
            t = t.crop( ((w-width)/2, (h-height)/4, (w-width)/2+width, (h-height)/4+height) )

            t.save(settings.MEDIA_ROOT + thumb, 'JPEG')
            os.chmod(settings.MEDIA_ROOT + thumb, 0666)
            thumb_obj = thumb
        return thumb_obj

References

Tags: django thumbnail pil