Рубрики
Без рубрики

Изменить размер изображения на сохранении в Django перед отправкой на Amazon S3 – без лямбда обязательный

Простой способ использования подушки и буфера памяти Я выравниваю на моем Django и Pyt … Помечено Django, AWS, Python, S3.

Простой способ использования подушки и буфера памяти

Я выравниваю на моем Django и Python Навыки в последнее время, и я столкнулся с довольно распространенной ситуацией, что не могу найти окончательное решение.

Дилемма

У меня есть Пользователи приложение с простым Модель профиля и я использую Django-хранилища Чтобы управлять загрузкой моего Изображения и другие Статические активы к Amazon S3 Отказ

Если пользователи загружают массивное изображение 4K , что никогда не будет отображаться больше 256 пикселей, Я не хочу хранить это Отказ Так что я хочу Изменить размер изображения на сохранении Перед загрузкой его AWS.

Для хранения изображений локально я просто должен установить подушку и Переопределить метод сохранения В моем профиле модели вроде так:

from PIL import Image

def save(self, *args, **kwargs):
    super().save(*args, **kwargs)

    img = Image.open(self.image.path)
    if img.height > 512 or img.width > 512:
        output_size = (512, 512)
        img.thumbnail(output_size)
        img.save(self.image.path)

Но он становится немного сложным при использовании ведра S3. Я получаю

NotimplementedError.

Значение исключения: Эта бэкэнда не поддерживает абсолютные пути.

Решение

Большинство из того, что я нашел онлайн предложил Удаление подушкой изменить размер и написание функции AWS Lambda обрабатывать размер на загрузке. Я изначально пробовал этот подход, но, согласно документам AWS, вы не должны использовать одно и то же ведро для ввода и вывода, что означает, что мне пришлось создать второе ведро S3 для изменений изображений. Я не мог выяснить, как получить эту настройку, работающую с Django-хранилищами.

Второй подход, который я нашел упомянул Использование буфера для сохранения измененного изображения в А потом экономя что к AWS. Примеры этого я обнаружил, что были неполными или использованными старыми версиями Python. Вот что на самом деле работало для меня, используя Python 3.8, Django 3.1.3 и подушка 8.0.1 :

user/models.py.

from app.utils import image_resize

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    image = models.ImageField(default="profile-default.png", upload_to="profile_pics")

    def __str__(self):
        return f"{self.user.username} Profile"

    def save(self, *args, **kwargs):
        image_resize(self.image, 512, 512)
        super().save(*args, **kwargs)

приложение/UTILS.PY.

from django.core.files import File
from pathlib import Path
from PIL import Image
from io import BytesIO

image_types = {
    "jpg": "JPEG",
    "jpeg": "JPEG",
    "png": "PNG",
    "gif": "GIF",
    "tif": "TIFF",
    "tiff": "TIFF",
}


def image_resize(image, width, height):
    # Open the image using Pillow
    img = Image.open(image)
    # check if either the width or height is greater than the max
    if img.width > width or img.height > height:
        output_size = (width, height)
        # Create a new resized "thumbnail" version of the image with Pillow
        img.thumbnail(output_size)
        # Find the file name of the image
        img_filename = Path(image.file.name).name
        # Spilt the filename on "." to get the file extension only
        img_suffix = Path(image.file.name).name.split(".")[-1]
        # Use the file extension to determine the file type from the image_types dictionary
        img_format = image_types[img_suffix]
        # Save the resized image into the buffer, noting the correct file type
        buffer = BytesIO()
        img.save(buffer, format=img_format)
        # Wrap the buffer in File object
        file_object = File(buffer)
        # Save the new resized file as usual, which will save to S3 using django-storages
        image.save(img_filename, file_object)

Я Переопределение метода сохранения Тем не менее, и вызывая функцию, которую я поместил в UTILS.PY моего основного приложения. Следующее происходит в image_resize Функция:

Image_Function Проверяет, если изображение слишком широко или высокое И, если оно есть, сначала сохраняйте измененную версию в буфер памяти, а затем на S3. Вернуться в метод сохранения, мы называем Super (). Сохранить () сохранить оставшиеся поля. Super (). Сохранить () нужно вызывать после image.save () или как оригинал, так и измененные изображения будут загружены на S3.

Я надеюсь, что это было полезно для кого-то. Как всегда, Спасибо за чтение и счастливого Рождества и счастливых праздников!

Оригинал: “https://dev.to/ninjasoards/resize-image-on-save-in-django-before-sending-to-amazon-s3-no-lambda-function-required-23f2”