Первое, что мы установим, это django-cleanup. Весьма полезная таблетка, которая при удалении статей, или даже generic fk связей удаляет вслед и изображения и прочие медиа файлы.
Приложение django-cleanup автоматически удаляет файлы для FileField, ImageField и подклассов. При изменении значения FileField и сохранении модели старый файл удаляется. При удалении модели с полем FileField файл также удаляется. Файл, заданный как значение по умолчанию для FileField, не будет удален.
Установка django-cleanup
В консоли: pip install django-cleanup
Результат установки:
(venv) PS C:\Users\Razilator\Desktop\Courses\App\backend> pip install django-cleanup
Collecting django-cleanup
Using cached django_cleanup-6.0.0-py2.py3-none-any.whl (10.0 kB)
Installing collected packages: django-cleanup
Successfully installed django-cleanup-6.0.0
Далее нам необходимо добавить этот модуль в установленные приложения settings.py:
backend/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sites',
'django.contrib.sitemaps',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'mptt',
'debug_toolbar',
'taggit',
'captcha',
'django_ckeditor_5',
'django_cleanup.apps.CleanupConfig',
'modules.blog.apps.BlogConfig',
'modules.system.apps.SystemConfig',
]
Пояснение:
- Добавил
'django_cleanup.apps.CleanupConfig'
в наши установленные приложения Django.
Ресайзинг/оптимизация изображения
А теперь создадим функцию оптимизации изображения
В одном из уроков мы создавали файл utils.py в модуле system, давайте там и создадим эту функцию:
modules/system/services/utils.py
from PIL import Image
def image_optimiser(image_path, height, width):
"""
Оптимизация изображений
"""
img = Image.open(image_path)
if img.mode != 'RGB':
img = img.convert('RGB')
if img.height > height or img.width > width:
output_size = (height, width)
img.thumbnail(output_size)
img.save(image_path)
Пояснение:
- Мы используем для оптимизации библиотеку Pillow
- В аргументы мы передаем путь до изображения, желаемую высоту и ширину.
Теперь добавим данную функцию в профиль при сохранении:
modules/system/models/profiles.py
def save(self, *args, **kwargs):
"""
Сохранение параметров модели при их отсутствии заполнения
"""
if not self.slug:
self.slug = unique_slugify(self, self.user.username)
if self.slug:
self.slug = self.slug.lower()
super().save(*args, **kwargs)
if self.avatar:
image_optimiser(self.avatar.path, height=300, width=300)
Почему необходимо добавить после метода def save()
?
Потому что, при сохранении мы ещё не загрузили изображение, а как проходит полное сохранение, то изображение уже находится в нужном месте по пути. Поэтому его можно оптимизировать, иначе мы получим ошибку.
Но если мы сохранили статью вновь, после редактирования, или других действий к ней, то мы будем снова и снова вызывать функцию оптимизации изображения. Чтобы решить эту проблему, я добавил следующее:
К классу нашего Profile я добавил инициализацию.
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__avatar = self.avatar if self.pk else None
Пояснение:
- Где в переменную
self.__avatar
сохраняю текущее изображениеself.avatar
, если существует ключ, если его нет, то значениеself.__avatar = None
.
Далее, меняем метод оптимизации после сохранения:
def save(self, *args, **kwargs):
"""
Сохранение параметров модели при их отсутствии заполнения
"""
if not self.slug:
self.slug = unique_slugify(self, self.user.username)
if self.slug:
self.slug = self.slug.lower()
super().save(*args, **kwargs)
if self.__avatar != self.avatar and self.avatar:
image_optimiser_task.delay(self.avatar.path, height=300, width=300)
Пояснение:
- Мы сравниваем переменную
self.__avatar
при сохранении с новым изображением, и если эти изображения разные, мы вызываем функцию оптимизации.
На этом установка закончена, функция по оптимизации изображения добавлена, модуль django-cleanup все сделает автоматически. Мы можем доже проверить это на деле.
Я установлю себе изображение размером 563x553px, весом 30.5 Kb. После оптимизации, вес составил 10 Kb, а размер 300x295px.
Для подробностей я скопировал аватарку оригинала в то же место, где сохранена аватарка установленная и оптимизированная на сайте.


Теперь я попробую ее удалить через сайт, и после удаления, аватарка исчезла, осталась лишь та, которую я скопировал сюда вручную:
