This is a typical use-case : your site/app allows users to upload a picture. But you don’t want to store full size 8Mb picture, and still, it’s comfortable for the user to not have to manually resize the image before uploading it. The solution : resizing the image “on the fly” when receiving it on the server side.
Another use-case, also quite common : you need to generate a thumbnail for the uploaded picture. The following code will help you too.
This script is re-sizing the image only if it’s a new PicturePost (we check that the object key isn’t set).
We’re doing some calculation to get the right ratio before re-sizing the image. We can’t use the thumbnail() method because we want to resize based only on the width of the image. The thumbnail() method will resize the image based on the biggest between width and height.
We convert the image to jpeg with a 90 quality (the default is 75, 100 meaning no jpeg compression at all).
We also keep the exif information if its exists. By default, it’ll disappear, so we have to manually add them again when saving the resized file.
Once it’s resized, we save the object into the database.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
import PIL from PIL import Image from django.db import models from django.core.files.uploadedfile import InMemoryUploadedFile from django.utils.six import StringIO class PicturePost(models.Model): # Picture picture = models.ImageField(upload_to='uploads/%Y/%m/%d/') def save(self, *args, **kwargs): # Do extra stuff before saving # If new post, get the picture and resize it on the fly if self.pk is None: # 1200px width maximum basewidth = 1200 img = Image.open(self.picture) # Keep the exif data exif = None if 'exif' in img.info: exif = img.info['exif'] width_percent = (basewidth/float(img.size[0])) height_size = int((float(img.size[1])*float(width_percent))) img = img.resize((basewidth, height_size), PIL.Image.ANTIALIAS) output = StringIO() # save the resized file to our IO ouput with the correct format and EXIF data ;-) if exif: img.save(output, format='JPEG', exif=exif, quality=90) else: img.save(output, format='JPEG', quality=90) output.seek(0) self.picture = InMemoryUploadedFile(output, 'ImageField', "%s.jpg" % self.picture.name, 'image/jpeg', output.len, None) super(CarPost, self).save(*args, **kwargs) |
You can also use the same logic to create a thumbnail of the image and store it into another ImageField field. 😉
it looks pretty good, but can u explane from where did u get
“super(CarPost,” ?
ur model is PicturePost and i cant see any PicturePost imports.
and how to combine ur code with :
class Profile(models.Model):
user = foreignkey to User model.
avatar = imagefield…. blabbla.
ProfileUpdateView(UpdateView):
……….
………