Evgenii Legotckoi
09 лютого 2022 р. 17:11

Django - Урок 056. Як конвертувати зображення у формат WEBP при збереженні у ImageField

WEBP - це формат стиснення зображень, запропонований Google в 2010 році. Головною його перевагою є низький розмір без видимих втрат якості, порівняно з такими форматами, як JPEG або PNG. Тому логічно використовувати цей формат для зберігання зображень на сайті, особливо якщо у вас немає необхідності зберігати оригінали зображень на сайті.

Після тривалих пошуків я так і не знайшов готового та простого рішення, яке б підтримувало конвертацію зображень у формат WEBP на льоту.
Тому вирішив написати свій варіант, який у підсумку складається з пари десяток рядків та простий як дерев'яна дошка.


Реалізація

Вся реалізація складається із двох частин:

  • WEBPFieldFile - клас спадкоємець від ImageFieldFile, який здійснює збереження файлу з автоматичною конвертацією в WEBP формат.
  • WEBPField - клас спадковий від ImageField, який використовує WEBPFieldFile замість ImageFieldFile

І все це розміщується в одному файлі fields.py.

Для роботи із зображеннями знадобиться бібліотека Pillow. Тому встановимо її. Втім, навіть просто для використання полів ImageField вам буде потрібна ця бібліотека.

  1. pip install Pillow

fields.py

Створіть у своєму додатку файли fields.py і додайте до нього наступний код

  1. # -*- coding: utf-8 -*-
  2.  
  3. import io
  4.  
  5. from PIL import Image
  6. from django.core.files.base import ContentFile
  7. from django.db import models
  8. from django.db.models.fields.files import ImageFieldFile
  9.  
  10.  
  11. class WEBPFieldFile(ImageFieldFile):
  12.  
  13. def save(self, name, content, save=True):
  14. content.file.seek(0)
  15. image = Image.open(content.file)
  16. image_bytes = io.BytesIO()
  17. image.save(fp=image_bytes, format="WEBP")
  18. image_content_file = ContentFile(content=image_bytes.getvalue())
  19. super().save(name, image_content_file, save)
  20.  
  21.  
  22. class WEBPField(models.ImageField):
  23. attr_class = WEBPFieldFile
  24.  

Як бачите, в даному коді в класі WEBPFieldFile перевизначено метод save() який отримує як вхідний аргумент ім'я та вміст файлу для збереження, конвертує вміст файлу у формат WEBP і після чого методом базового класу зберігає файл на диск. А клас WEBPField такий самий як і ImageField з тією лише різницею, що використовує модифікований фаріант класу для обробки зображення.

models.py

А тепер давайте скористаємося новим полем зображення у нашій моделі для фотографії.

  1. # -*- coding: utf-8 -*-
  2.  
  3. import os
  4. import uuid
  5.  
  6. from django.conf import settings
  7. from django.db import models
  8. from django.utils.translation import gettext_lazy as _
  9.  
  10. from photo.fields import WEBPField
  11.  
  12.  
  13. def image_folder(instance, filename):
  14. return 'photos/{}.webp'.format(uuid.uuid4().hex)
  15.  
  16.  
  17. class Photo(models.Model):
  18. user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
  19. height = models.IntegerField(verbose_name=_('Height'), default=0, blank=True, null=True)
  20. width = models.IntegerField(verbose_name=_('Width'), default=0, blank=True, null=True)
  21. image = WEBPField(
  22. verbose_name=_('Image'),
  23. upload_to=image_folder,
  24. height_field='height',
  25. width_field='width'
  26. )

Як бачите, використання даного поля WEBPField нічим не відрізняється від використання стандартного поля ImageField .

А як бонус в даному коді до функції image_folder я додав генерування випадкового унікального імені файлу за допомогою uuid .

Вам це подобається? Поділіться в соціальних мережах!

Владислав Меленчук
  • 19 лютого 2022 р. 12:30

Очень годно!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
  • Останні коментарі
  • Evgenii Legotckoi
    16 квітня 2025 р. 17:08
    Благодарю за отзыв. И вам желаю всяческих успехов!
  • IscanderChe
    12 квітня 2025 р. 17:12
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    01 квітня 2025 р. 11:41
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    09 березня 2025 р. 21:02
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    09 березня 2025 р. 16:14
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…