While working on a recent Django project I had the need to create thumbnails from images residing on a remote server to store within one of my Django app models. The wrinkle was that I wanted to programmatically make the thumbnail "on the fly" before storage since I didn't want to waste space storing the original, much larger, image. So if you are in a similar situation, where do you start?
Considering the vast array of libraries for Python, I hunted down the most referenced one, Python Imaging Library(PIL), and installed it. For purposes of this tutorial, I'll presuppose that you've already installed PIL on your platform and have some experience manipulating images using it. I'm working on OS X (Snow Leopard) and had no issues getting PIL working but if you do, follow the directions on this blog post. (I can't help if you're on Windows) If you can run the command 'from PIL import Image' from the python prompt then you've installed it properly, Django shouldn't complain, and the code below should work.
The Thumbnail Model
Once you've installed PIL your hardest struggles are over. For our simplified example we'll create a custom image model with 'url' and 'thumb' attributes. The 'url' attribute will store the url of the image in the event you need to reference the original picture and 'thumb' will be an ImageField that stores the location of the thumbnail we create. We'll define a function called 'create_thumb' that will perform the image manipulation. Here's what the Model looks like, including the required imports:
import Image import os import urllib from django.core.files import File ..... .... .. class Thumbnail(models.Model): url =models.CharField(max_length=255, unique=True) # Set the upload_to parameter to the directory where you'll store the # thumbs thumb = models.ImageField(upload_to='thumbs', null=true) """ Pulls image, converts it to thumbnail, then saves in thumbs directory of Django install """ def create_thumb(self): if self.url and not self.thumb: image = urllib.urlretrieve(self.url) # Create the thumbnail of dimension size size=128,128 t_img = Image.open(image) t_img.thumbnail(size) # Get the directory name where the temp image was stored # by urlretrieve dir_name = os.path.dirname(image) # Get the image name from the url img_name = os.path.basename(self.url) # Save the thumbnail in the same temp directory # where urlretrieve got the full-sized image, # using the same file extention in os.path.basename() t_img.save(os.path.join(dir_name, "thumb" + img_name)) # Save the thumbnail in the media directory, prepend thumb self.thumb.save(os.path.basename("thumb" + self.url),File(open(os.path.join(dir_name, "thumb" + img_name)))
What is that Code Doing? Can it be Improved?
Although the code is commented pretty well, I'll give a bit more explanation. In Django, the ImageField doesn't actually store the image in your database. Instead, it is stored in a directory located on the path your 'MEDIA_ROOT' is configured to in the settings.py file. So make sure that this appropriately configured, then create the 'thumbs' subdirectory within that directory. That's what the 'upload_to' parameter is used for in the ImageField type.
The 'create_thumb' method should be called when you create an instance of the Thumbnail model. Here's an example of one way you could use it:
a = Thumbnail(url='http://url.to.the.image.you.want.a.thumbnail.of') a.create_thumb() a.save()
The 'create_thumb' method takes the url, creates the thumbnail, and saves it in the 'upload_to' directory. Since this is sample code I didn't put any provision for catching exceptions such as improper url provided or image processing errors - that would be one area I'd suggest you improve upon. Also, the thumbnails are saved under the same name of the image provided by the url with "thumb" prepended. You might wonder what happens if two urls have the same image name? Well, I'll tell you: The new thumb will overwrite the old so you will want to add code that creates a unique name for the image.
Besides the few caveats mentioned above, the code works as advertised and will make your life that much easier...at least when it comes to creating thumbnails. As usual, I only ask that if this post helped you, please leave a comment.