Resizing Django ImageField with Remote Storage

Recently I’ve been working on a project to move our photo experience to store images on Amazon’s S3 service instead of the local server, in hopes to gain performance and move away from handling the maintenance static files tend to have.

There are many examples online of saving directly to Amazon and not using Django’s Storage Backend, however these examples tend to not give the best overall experience, specially when the site is for a customer.  Why keep files on Amazon after a customer has deleted the relationship on your site?  Paying for the extra space is something I’m not looking to do.

Luckily during this search I learned about Django’s Storage API and loved the concept and found a great package called django-storage that already has implemented S3 support.  The documentation could use a bit of work, but isn’t too hard to get a handle of.

Now that I had the capability to save images to S3 I also wanted the possibility to resize said image and create a thumbnail.

The issue with this is that all examples I could find where in regards to either files saved on disk or stored in memory, neither of which was my case.

Below is example code that allows you to resize images using Django’s models.ImageField and PIL library.  Hopefully this saves someone some time as it took me a few hours to come up with a solution.


def _resize_image(self):
try:
import urllib2 as urllib
from PIL import Image
from cStringIO import StringIO
from django.core.files.uploadedfile import SimpleUploadedFile

'''Open original photo which we want to resize using PIL's Image object'''
img_file = urllib.urlopen(self.image.url)
im = StringIO(img_file.read())
resized_image = Image.open(im)

'''Convert to RGB if necessary'''
if resized_image.mode not in ('L', 'RGB'):
resized_image = resized_image.convert('RGB')

'''We use our PIL Image object to create the resized image, which already
has a thumbnail() convenicne method that constrains proportions.
Additionally, we use Image.ANTIALIAS to make the image look better.
Without antialiasing the image pattern artificats may reulst.'''
resized_image.thumbnail(self.image_max_resolution, Image.ANTIALIAS)

'''Save the resized image'''
temp_handle = StringIO()
resized_image.save(temp_handle, 'jpeg')
temp_handle.seek(0)

''' Save to the image field'''
suf = SimpleUploadedFile(os.path.split(self.image.name)[-1].split('.')[0],
temp_handle.read(), content_type='image/jpeg')
self.image.save('%s.jpg' % suf.name, suf, save=True)
except ImportError:
pass

5 Responses to Resizing Django ImageField with Remote Storage

  1. David says:

    YOU MADE MY DAY (!)

  2. Arthur says:

    Dude, You could post you entire model class as well that will help more! good stuff though ! thanks!

  3. Eric Loes says:

    @Arthur – Thanks for the suggestion. I’ll update the post this weekend

  4. John says:

    Eric,

    did you consider the sorl thumbnail project? It already does the resizing for you and operates on top of existing file/image fields.
    I am using that right now and I am myself considering to move to S3, so I hope the two play nice together.

  5. Azhar says:

    Thank you so much!

    I used this as a reference for a task today which required me to compress large images from a Nokia Lumia and serve the thumbnails, all from S3.

    This was a god send after spending half the day quite frustrated.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>