django - How to edit/manipulate uploaded images on the fly before saving
Sometimes you need to perform certain operations on user uploaded images before saving them in Django. These operations may include cropping images, rotating them, generating thumbnails or compressing them. I'll show you how to do that.
You'll need to have Pillow installed for that.
Sample model¶
Below is a sample model which has two fields - image
and thumbnail
.
# models.py
from django.db import models
class MyModel(models.Model):
image = models.ImageField()
thumbnail = models.ImageField()
Now let's say we want to auto generate thumbnails from the image uploaded by the user.
Function for generating thumbnails¶
We'll create a new function called make_thumbnail
which will
create thumbnails for the given image. Keep this in code wherever you like.
This code works for Django >= 1.7.
from io import BytesIO
from django.core.files import File
from PIL import Image
def make_thumbnail(image, size=(100, 100)):
"""Makes thumbnails of given size from given image"""
im = Image.open(image)
im.convert('RGB') # convert mode
im.thumbnail(size) # resize image
thumb_io = BytesIO() # create a BytesIO object
im.save(thumb_io, 'JPEG', quality=85) # save image to BytesIO object
thumbnail = File(thumb_io, name=image.name) # create a django friendly File object
return thumbnail
Here's some explanation about the code:
im.convert(RGB)
is done to convert the image's mode to RGB. Because sometimes Pillow throws an error when we try to save an image in JPEG format if the image is a GIF with a limited palette.im.thumbnail(size)
is a method of Pillow'sImage
class which scales the image to the given size while keeping the aspect ratio.thumbnail = File(thumb_io, name=image.name)
creates a Django-friendlyFile
object which we can use as the value for a model'sImageField
.
Other than that, the code is fairly basic. This is just to give you an idea about manipulating images on the fly.
Calling the function from the model¶
And here's how you'd call the function from the model:
# models.py
# import the `make_thumbnail` function
from some_file import make_thumbnail
class MyModel(models.Model):
image = models.ImageField()
thumbnail = models.ImageField()
def save(self, *args, **kwargs):
self.thumbnail = make_thumbnail(self.image, size=(100, 100))
super().save(*args, **kwargs)
That is it¶
You can adapt and modify the code to perform any operations you like on the images, for example crop them, or even apply Instagram like fancy filters.
It's up to you.