Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Django – Create thumbnail on model save. Creates a thumbnail when saving a model by cropping it to square and resizing to 280x280. The thumbnail is not created if the original image is smaller than 280x280, doesn't exist, or if a thumbnail already exists.
from cStringIO import StringIO
from django.core.files.base import ContentFile
from django.db import models
from PIL import Image
 
class SomeModel(models.Model):
image = models.ImageField(upload_to='images', blank=True)
thumbnail = models.ImageField(upload_to='thumbnails', blank=True)
 
def create_thumbnail(self):
# Don't do anything if there is no image to thumbnail.
# Also, don't overwrite an existing thumbnail
# (prevents a new thumbnail from being created every save).
if not self.image or self.thumbnail:
return
 
image = Image.open(self.image.file)
 
# If the image is smaller than 280 x 280,
# don't bother creating a thumbnail.
width, height = image.size
if width < 280 or height < 280:
return
 
# Crop as little as possible to square, keeping the center.
if width > height:
delta = width - height
left = int(delta / 2)
upper = 0
right = height + left
lower = height
else:
delta = height - width
left = 0
upper = int(delta / 2)
right = width
lower = width + upper
image = image.crop((left, upper, right, lower))
 
# Create the thumbnail as a 280 x 280 square.
image.thumbnail((280, 280), Image.ANTIALIAS)
 
# Save the thumbnail in the FileField.
# Using Image.save(content, 'jpeg') seems to work for pngs too.
buf = StringIO()
image.save(buf, 'jpeg', quality=95)
cf = ContentFile(buf.getvalue())
self.thumbnail.save(name=self.image.name, content=cf, save=False)
 
def save(self):
self.create_thumbnail()
super(SomeModel, self).save()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment