[Django]-How to resize an ImageField image before saving it in python Django model

26👍

You could use the django-resized library. It resizes images when uploaded and stores them for you.

Usage

from django_resized import ResizedImageField

class Posts(models.Model):
    title = models.CharField(max_length=200, blank=True)
    body = models.TextField(blank=True)
    created_at = models.DateTimeField(default=datetime.datetime.now)
    post_image = ResizedImageField(size=[500, 300], upload_to=get_image_path, blank=True, null=True)

    def __str__(self):
        return self.title

Options

  • size – max width and height, for example [640, 480]
  • crop – resize and crop. [‘top’, ‘left’] – top left corner, [‘middle’, –
    ‘center’] is center cropping, [‘bottom’, ‘right’] – crop right bottom corner.
  • quality – quality of resized image 1..100
  • keep_meta – keep EXIF and other meta data, default True
  • force_format – force the format of the resized image, available formats are the one supported by pillow, default to None
👤Stevy

2👍

**

This will work
**First of all install "PIL Fork" using ‘pip install pillow

from PIL import Image


def __str__(self):
    return self.title


def save(self, *args, **kwargs):
    super(Posts, self).save(*args, **kwargs)
    imag = Image.open(self.post_image.path)
    if imag.width > 400 or imag.height> 300:
        output_size = (400, 300)
        imag.thumbnail(output_size)
        imag.save(self.post_image.path)
class Meta:
    verbose_name_plural = "Posts"
👤Dennis

1👍

You can use this method to resize the image before saving it: (you need pip install pillow)

import os
from io import BytesIO
from PIL import Image as PilImage
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile

def resize_uploaded_image(image, max_width, max_height):
    size = (max_width, max_height)

    # Uploaded file is in memory
    if isinstance(image, InMemoryUploadedFile):
        memory_image = BytesIO(image.read())
        pil_image = PilImage.open(memory_image)
        img_format = os.path.splitext(image.name)[1][1:].upper()
        img_format = 'JPEG' if img_format == 'JPG' else img_format

        if pil_image.width > max_width or pil_image.height > max_height:
            pil_image.thumbnail(size)

        new_image = BytesIO()
        pil_image.save(new_image, format=img_format)

        new_image = ContentFile(new_image.getvalue())
        return InMemoryUploadedFile(new_image, None, image.name, image.content_type, None, None)

    # Uploaded file is in disk
    elif isinstance(image, TemporaryUploadedFile):
        path = image.temporary_file_path()
        pil_image = PilImage.open(path)

        if pil_image.width > max_width or pil_image.height > max_height:
            pil_image.thumbnail(size)
            pil_image.save(path)
            image.size = os.stat(path).st_size

    return image

Then use it in the clean method of the image field in your form:

class ImageForm(forms.Form):
    IMAGE_WIDTH = 450
    IMAGE_HEIGHT = 450
    
    image = forms.ImageField()

    def clean_image(self):
        image = self.cleaned_data.get('image')
        image = resize_uploaded_image(image, self.IMAGE_WIDTH, self.IMAGE_HEIGHT)
        return image

To understand how the resize_uploaded_image method works, you may read about how Django handles uploaded files in the docs, here and here.

-1👍

You can use the django-imagekit library.

Installation

  1. Install Pillow. (If you’re using an ImageField in Django,
    you should have already done this.)
  2. pip install django-imagekit
  3. Add 'imagekit' to your INSTALLED_APPS list in your project’s settings.py

Models.py

from django.db import models
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill

class Profile(models.Model):
    avatar = models.ImageField(upload_to='avatars')
    avatar_thumbnail = ImageSpecField(source='avatar',
                                  processors=[ResizeToFill(100, 50)],
                                  format='JPEG',
                                  options={'quality': 60})

Pay attention to the source attribute of ImageSpecField which directs to the actual image field (avatar in this case) as ImageSpecField are virtual in nature, you can read more about it here

Using in your template

<img src="{{ profile.avatar_thumbnail.url }}" />

Leave a comment