Evgenii Legotckoi
Evgenii Legotckoi09 лютого 2022 р. 06:11

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

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

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


Реалізація

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

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

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

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

pip install Pillow

fields.py

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

# -*- coding: utf-8 -*-

import io

from PIL import Image
from django.core.files.base import ContentFile
from django.db import models
from django.db.models.fields.files import ImageFieldFile


class WEBPFieldFile(ImageFieldFile):

    def save(self, name, content, save=True):
        content.file.seek(0)
        image = Image.open(content.file)
        image_bytes = io.BytesIO()
        image.save(fp=image_bytes, format="WEBP")
        image_content_file = ContentFile(content=image_bytes.getvalue())
        super().save(name, image_content_file, save)


class WEBPField(models.ImageField):
    attr_class = WEBPFieldFile

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

models.py

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

# -*- coding: utf-8 -*-

import os
import uuid

from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _

from photo.fields import WEBPField


def image_folder(instance, filename):
    return 'photos/{}.webp'.format(uuid.uuid4().hex)


class Photo(models.Model):
    user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    height = models.IntegerField(verbose_name=_('Height'), default=0, blank=True, null=True)
    width = models.IntegerField(verbose_name=_('Width'), default=0, blank=True, null=True)
    image = WEBPField(
        verbose_name=_('Image'),
        upload_to=image_folder,
        height_field='height',
        width_field='width'
    )

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

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

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

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

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

Очень годно!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
Ua

Qt - Тест 001. Сигналы и слоты

  • Результат:84бали,
  • Рейтинг балів4
Ua

Qt - Тест 001. Сигналы и слоты

  • Результат:42бали,
  • Рейтинг балів-8
ОК

Qt - Тест 001. Сигналы и слоты

  • Результат:47бали,
  • Рейтинг балів-6
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 11:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 жовтня 2024 р. 14:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 08:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 07:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 11:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Дмитрий
Дмитрий03 лютого 2025 р. 06:24
Создание deb-пакета. Как создать ярлык на рабочем столе после установки собственного deb-пакета? Всем привет. Сделал свой deb-пакет с программой. Всё устанавливается и работает. Ставлю по пути /usr/bin/my_application. Как для пользователя при установке пакета сразу создать ярлык на раб…
NW
Nayo Wai30 січня 2025 р. 09:22
не запускается компьютер!!! Не запускается компьютер (точнее работает блок , но сам монитор вообще жесть)В общем я ничего с интернета не скачивала в последнее время. На компе никаких левых пр…
n
nkly03 січня 2025 р. 02:52
Нужно запретить перемещение только некоторых итемов, остальные перемещать можно. Вопрос решен. Узнать QModelIndex элемента на который мы перетаскиваем другой элемент, можно с помощью функции indexAt(event->position().toPoint()) представления QTreeViev вызываемой в переопр…
M
Marsel16 серпня 2023 р. 14:26
OAuth2.0 через VK, получение email Спасибо большое за помощь и простите за то что отнял время своей невнимательностью.
Evgenii Legotckoi
Evgenii Legotckoi24 червня 2024 р. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.

Слідкуйте за нами в соціальних мережах