@Lepilov

Как правильно настроить post_save сигнал для удаления изображения?

Есть модель с полем img ( фото пользователя)
class Profile(models.Model):
    img = models.ImageField(upload_to=user_directory_path, verbose_name='Ваше фото')


# user image file will be uploaded to
def user_directory_path(instance, filename):
    return 'images/{0}/{1}'.format(instance.name, filename)


Я хочу настроить удаление старого файла в поле img, когда пользователь загружает новую аватарку. Для этого сделал сигналы

# Delete old profile img file
@receiver(post_init, sender=Profile)
def backup_image_path(sender, instance, **kwargs):
    if instance.img:
        instance._current_imagen_file = instance.img

@receiver(post_save, sender=Profile)
def delete_old_image(sender, instance, **kwargs):
    if hasattr(instance, '_current_imagen_file'):
        if instance._current_imagen_file != instance.img.path:
            instance._current_imagen_file.delete(save=False)


Если загружать новое фото, то старое удаляется, но при этом если я с админки не внося никаких изменений в профиль пользователя просто нажимаю на сохранить, то файл так же удаляется.
Насколько я помню у меня не было такой проблемы когда я загружал в корень папки img, появилось когда добавил def user_directory_path
Что не так с кодом?
  • Вопрос задан
  • 66 просмотров
Решения вопроса 1
sergey-gornostaev
@sergey-gornostaev Куратор тега Django
Седой и строгий
Лучше использовать pre_save, чтобы иметь возможно сравнить старое и новое значение поля img:
@receiver(pre_save, sender=Profile)
def my_handler(sender, instance, **kwargs):
    if instance.pk:
        old = Profile.objects.get(pk=instance.pk)
        path = old.img.path
        if path != instance.img.path:
            os.remove(path)

Но ещё лучше такие вещи делать с помощью фонового задания, периодически удаляющего файлы, на которые нет ссылок в БД.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы