Простой способ использования подушки и буфера памяти
Я выравниваю на моем 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”