简体   繁体   中英

How to get content of Django ImageField before it is saved?

I'm trying to resize an image while saving an instance of my model.

class Picture(models.Model):
  image_file = models.ImageField(upload_to="pictures")
  thumb_file = models.ImageField(upload_to="pictures", editable=False)
  def save(self, force_insert=False, force_update=False):
    image_object = Image.open(self.image_file.path)
    #[...] nothing yet
    super(Picture, self).save(force_insert, force_update)

The problem is that self.image_file.path does not exist before the model is being saved. It returns a correct path, but the image is not there yet. Since there is no image, I can't open it in PIL for resize.

I want to store the thumbnail in thumb_file (another ImageField), so I need do the processing before saving the model.

Is there a good way to open the file (maybe get the tmp image object in memory) or do I have to save the whole model first, resize and then save again ?

I used this snippet :

import Image

def fit(file_path, max_width=None, max_height=None, save_as=None):
    # Open file
    img = Image.open(file_path)

    # Store original image width and height
    w, h = img.size

    # Replace width and height by the maximum values
    w = int(max_width or w)
    h = int(max_height or h)

    # Proportinally resize
    img.thumbnail((w, h), Image.ANTIALIAS)

    # Save in (optional) 'save_as' or in the original path
    img.save(save_as or file_path)

    return True

And in models:

def save(self, *args, **kwargs):
    super(Picture, self).save(*args, **kwargs)
    if self.image:
        fit(self.image_file.path, settings.MAX_WIDTH, settings.MAX_HEIGHT)

On your model save method the field value will be a valid FileField or ImageFileField in the case of an ImageField . This django class implements the object file interface (ie read , write ) and it works even before the file is saved with your model, so you can use it as the parameter to PIL.Image.open :

class Picture(models.Model):
    image_file = models.ImageField(upload_to="pictures")
    thumb_file = models.ImageField(upload_to="pictures", editable=False)

    def save(self, force_insert=False, force_update=False):
        img = Image.open(self.image_file)
        # work with img, is an Image object
        super(Picture, self).save(force_insert, force_update)

This works on django >= 1.5 .

Maybe you can open the file directly and pass the resulting file handle to Image.open :

image_object = Image.open(self.image_file.open())

Sorry, I can't test that now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM