Monday 27 October 2014

create thumbnail on image upload in django

Standard
Django does not provide any standard way of organizing thumbnails.
Even though community has some applications to work with thumbnails, they are usually over kill if You only want to create a thumbnail for an ImageField. So here is my solution to handle thumbnails.

To hande thumbnails I over-wrote my model's save method to read original image field into a StringIO, manipulate the image and save it into a thumbnail image.
first of you need a python PIL library so first install it :

sudo apt-get install libjpeg libjpeg-dev libfreetype6 libfreetype6-dev zlib1g-dev
pip install PIL 

Here is the code.



class User(models.Model):
    profile_pic = models.ImageField(upload_to = 'user/',null=True,blank=True)
    thumb_pic = models.ImageField(upload_to = 'user/thumb/',null=True,blank=True)
   
    def delete(self, *args, **kwargs):
        storage, path = self.profile_pic.storage, self.profile_pic.path
        storage1, path1 = self.thumb_pic.storage, self.thumb_pic.path
        super(User, self).delete(*args, **kwargs)
        storage.delete(path)
        storage1.delete(path1)

    def save(self, *args, **kwargs):
        try:
            this = User.objects.get(id=self.id)
            self.create_thumbnail()
            if this.profile_pic != self.profile_pic:
                this.profile_pic.delete(save=False)
                this.thumb_pic.delete(save=False)
        except: pass
        super(User, self).save(*args, **kwargs)

    def create_thumbnail(self):
        if not self.profile_pic:
            return
        from PIL import Image
        from cStringIO import StringIO
        from django.core.files.uploadedfile import SimpleUploadedFile
        import os
        THUMBNAIL_SIZE = (200,200)
        DJANGO_TYPE = self.profile_pic.file.content_type
        if DJANGO_TYPE == 'image/jpeg':
            PIL_TYPE = 'jpeg'
            FILE_EXTENSION = 'jpg'
        elif DJANGO_TYPE == 'image/png':
            PIL_TYPE = 'png'
            FILE_EXTENSION = 'png'
        image = Image.open(StringIO(self.profile_pic.read()))
        image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS)
        temp_handle = StringIO()
        image.save(temp_handle, PIL_TYPE)
        temp_handle.seek(0)
        suf = SimpleUploadedFile(os.path.split(self.profile_pic.name)[-1],temp_handle.read(), content_type=DJANGO_TYPE)
        self.thumb_pic.save('%s.%s'%(os.path.splitext(suf.name)[0],FILE_EXTENSION), suf, save=False)


this is so easy, just follow this code and your thumbnail is ready