Django оптимизировать, переименовать, изменить размер изображения при первом сохранении

Я хочу изменить размер и оптимизировать изображение при сохранении. Но только при первом сохранении изображения, а не при всех сохранениях. Также я хотел бы переименовать файл и автоматически перезаписать старый файл при загрузке нового файла.

Цель состоит в том, чтобы

  • переименуйте изображения в /menues/{shopid}.jpg (также измените с png на jpg)
  • оптимизировать изображение для Интернета
  • изменить масштаб ширины и высоты изображения до максимальной ширины / высоты 1400

Ниже приведен код, который я создал до сих пор.

def get_upload_path(instance, filename):
    name, ext = 'menu', os.path.splitext(filename)[1]
    if instance.shopid:  # shopid is defined by form view right before create()
        return os.path.join("menues", instance.shopid + ext)
    return os.path.join('menues', filename)

def scale_dimensions(width, height, longest_side):
    if width > height:
        if width > longest_side:
            ratio = longest_side*1./width
            return (int(width*ratio), int(height*ratio))
    elif height > longest_side:
        ratio = longest_side*1./height
        return (int(width*ratio), int(height*ratio))
    return (width, height)

from PIL import Image
import os
MAX_MENU_IMG_MB = 10.0
IMG_RESIZE_LONGEST_SIDE = 1400

class Shop(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    shopid = models.CharField(max_length=14, blank=True, editable=False)
    name = models.CharField()
    menu = models.ImageField(_("Photo (Max %sMB)") % str(MAX_MENU_IMG_MB), upload_to=get_upload_path, null=False, blank=False)

    def save(self):
        super(Shop, self).save()

        if self.menu:
            image = Image.open(self.menu.path)
            (width, height) = image.size
            (new_width, new_height) = scale_dimensions(width, height, longest_side=IMG_RESIZE_LONGEST_SIDE)
            if new_width < width or new_height < height:
                image = image.resize((new_width, new_height))
            image.save("%s.jpg" % self.menu.path.split('.')[0], format='JPEG', quality=70, optimize=True)

перед вызовом super().save() можно сделать first_save = not self.id. Вы можете использовать first_save после супервызова, чтобы знать, что это первое сохранение.

Ramkishore M 16.04.2018 10:57
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
361
1

Ответы 1

Используйте init, чтобы увидеть изменение изображения

def __init__(self):
    super(Shop, self).__init__(*args, **kwargs)
    self.__previous_menu = self.menu if self.id else None

При сохранении удалите предыдущее изображение и исходную версию нового изображения.

def save(self, *args, **kwargs):
    super().save(*args, **kwargs)
    previous_menu = self.__previous_menu
    if self.menu != previous_menu:
        # delete old image if changed
        if previous_menu:
            os.remove('{}/{}'.format(
                settings.MEDIA_ROOT,previous_menu.name).replace("\\","/"))

        org_file = self.menu
        # resize logic here

        self.__previous_menu = self.menu # to avoid infinite loop
        # remove original version of new image
        os.remove('{}/{}'.format(
            settings.MEDIA_ROOT,org_file.name).replace("\\","/"))
        self.save()

Другие вопросы по теме