Как получить содержимое Django ImageField до его сохранения? - PullRequest
3 голосов
/ 08 января 2012

Я пытаюсь изменить размер изображения при сохранении экземпляра моей модели.

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)

Проблема в том, что self.image_file.path не существует до сохранения модели. Он возвращает правильный путь, но изображение еще не там. Поскольку изображения нет, я не могу открыть его в PIL для изменения размера.

Я хочу сохранить миниатюру в thumb_file (еще один ImageField), поэтому мне нужно выполнить обработку перед сохранением модели.

Есть ли хороший способ открыть файл (возможно, получить объект изображения tmp в памяти) или мне нужно сначала сохранить всю модель, изменить ее размер, а затем сохранить снова?

Ответы [ 3 ]

2 голосов
/ 08 января 2012

Я использовал этот фрагмент :

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

А в моделях:

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)
0 голосов
/ 16 апреля 2018

В методе вашей модели save значение поля будет действительным FileField или ImageFileField в случае ImageField.Этот класс django реализует интерфейс объектного файла (то есть read, write) и работает даже до сохранения файла в вашей модели, поэтому вы можете использовать его в качестве параметра для 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)

Это работает на Джанго >= 1.5.

0 голосов
/ 08 января 2012

Может быть, вы можете открыть файл напрямую и передать полученный дескриптор файла на Image.open:

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

Извините, я не могу проверить это сейчас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...