Home > Software design >  How to save pillow processed image in already existing Django object
How to save pillow processed image in already existing Django object

Time:09-04

I have created a object model as below

from django.db import models

# Create your models here.
class ImageModel(models.Model):
    image = models.ImageField(upload_to='images/')
    editedImg = models.ImageField(upload_to='images/')

    def delete(self, *args, **kwargs):
        self.image.delete()
        self.editedImg.delete()
        super().delete(*args, **kwargs)

And here is what i am trying to do in a function

from django.shortcuts import render
from EditorApp.forms import ImageForm
from EditorApp.models import ImageModel
from django.http import HttpResponseRedirect
from PIL import Image

def edit_column(request):
    codArr = request.POST.getlist('codArr[]')
    imgs = ImageModel.objects.first()
    orgImage = ImageModel.objects.first().image
    orgImage = Image.open(orgImage)
    croppedImg = orgImage.crop((int(codArr[0]), int(codArr[1]), int(codArr[2]), int(codArr[3])))
    # croppedImg.show()
    # imgs.editedImg = croppedImg
    # imgs.save()
    return HttpResponseRedirect("/editing/")

What i am trying to do is the codArr consists of coordinates of top(x, y) and bottom(x, y) in the array form(Which is not an issue and is tested(croppedImg.show() showed the desired cropped image) and handled and used to crop the image). Image crop is working fine. But what i am trying to do is to save the cropped image in editedImg of the model used above. The above commented one is what i tried but throw a error AttributeError: _committed

As i have not used any name for image in model as its not required. Kindly help please, Would be very thankfull.

CodePudding user response:

you should do it like this:

from io import BytesIO
from api.models import ProductPicture
from django.core import files

codArr = request.POST.getlist('codArr[]')
img_obj = ImageModel.objects.first()
orgImage = img_obj.image
orgImage = Image.open(orgImage)
croppedImg = orgImage.crop((int(codArr[0]), int(codArr[1]), int(codArr[2]), int(codArr[3])))
thumb_io = BytesIO()  # create a BytesIO object
croppedImg.save(thumb_io, 'png')
editedImg = files.File(thumb_io, name=file_name)
img_obj.editedImg = editedImg
img_obj.save()

CodePudding user response:

You can use Python's context manager to open the image and save it to the desired storage in that case I'm using the images dir.

Pillow will crop the image and image.save() will save it to the filesystem and after that, you can add it to Django's ImageField and save it into the DB.

The context manager takes care of the file opening and closing, Pillow takes care of the image, and Django takes care of the DB.

from PIL import Image

with Image.open(orgImage) as image:
    file_name = image.filename # Can be replaced by orgImage filename
    cropped_path = f"images/croped-{file_name}"
    # The crop method from the Image module takes four coordinates as input.
    # The right can also be represented as (left width)
    # and lower can be represented as (upper height).
    (left, upper, right, lower) = (20, 20, 100, 100)

    # Here the image "image" is cropped and assigned to new variable im_crop
    im_crop = image.crop((left, upper, right, lower))
    im_crop.save(cropped_path)
    imgs.editedImg = cropped_path
    imgs.save()

Pillow's reference

  • Related