Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

Вам придется удалить старое изображение вручную.

Абсолютный путь к изображению хранится в your_image_field.name. Так что вы бы сделали что-то вроде:

os.remove(your_image_field.name)

Но для удобства вы можете использовать связанный объект FieldFile, который обеспечивает легкий доступ к базовому файлу, а также предоставляет несколько удобных методов. См. Http://docs.djangoproject.com/en/dev/ref/models/fields/#filefield-and-fieldfile.

Ответ 2

Используйте django-cleanup

pip install django-cleanup

settings.py

INSTALLED_APPS = (
    ...
    'django_cleanup', # should go after your apps

)

Ответ 3

Используйте этот настраиваемый метод сохранения в вашей модели:

def save(self, *args, **kwargs):
    try:
        this = MyModelName.objects.get(id=self.id)
        if this.MyImageFieldName != self.MyImageFieldName:
            this.MyImageFieldName.delete()
    except: pass
    super(MyModelName, self).save(*args, **kwargs)

Он работает для меня на моем сайте. Эта проблема тоже беспокоила меня, и я не хотел делать очистку script вместо хорошей бухгалтерии в первую очередь. Сообщите мне, есть ли с ним проблемы.

Ответ 4

Перед обновлением экземпляра модели вы можете использовать метод FileField объекта FileField. Например, если FileField или ImageField назван как photo а экземпляр вашей модели - profile, то следующий файл удалит файл с диска.

profile.photo.delete(False)

Для получения дополнительной информации, вот документ Django

https://docs.djangoproject.com/en/1.11/ref/models/fields/#django.db.models.fields.files.FieldFile.delete

Ответ 5

Вы можете определить pre_save reciever в моделях:

@receiver(models.signals.pre_save, sender=UserAccount)
def delete_file_on_change_extension(sender, instance, **kwargs):
    if instance.pk:
        try:
            old_avatar = UserAccount.objects.get(pk=instance.pk).avatar
        except UserAccount.DoesNotExist:
            return
        else:
            new_avatar = instance.avatar
            if old_avatar and old_avatar.url != new_avatar.url:
                old_avatar.delete(save=False)

Мои аватры имеют уникальный URL для каждого человека, например, "avatars/ceb47779-8833-4719-8711-6f4e5cabb2b2.png". Если пользователь загружает новое изображение с другим расширением, например jpg, приемник delete_file_on_change_extension удаляет старое изображение, а затем сохраняет новое с помощью URL-адреса "avatars/ceb47779-8833-4719-8711-6f4e5cabb2b2.jpg" (в данном случае). Если пользователь загружает новое изображение с тем же расширением, django перезаписывает старое изображение в хранилище (на диске), поскольку пути к изображениям совпадают. Это прекрасно работает с AWS S3 django-storage.

Ответ 6

Вот приложение, которое по умолчанию удаляет файлы-сироты: django-smartfields. Он будет удалять файлы всякий раз, когда:

  • Значение поля
  • было заменено новым (загружено или установлено вручную) Поле
  • очищается через форму (в случае, если это поле не требуется, конечно)
  • удаляется экземпляр модели, содержащий поле.

Можно отключить эту функцию очистки с помощью аргумента: ImageField(keep_orphans=True) для каждого поля или глобально в настройках SMARTFIELDS_KEEP_ORPHANS = True.

from django.db import models

from smartfields import fields

class MyModel(models.Model):
    image = fields.ImageField()
    document = fields.FileField()

Ответ 7

Попробуйте, это будет работать, даже если старый файл будет удален

def logo_file(instance, filename):

    try:
        this = business.objects.get(id=instance.id)
        if this.logo is not None:
            path = "%s" % (this.logo)
            os.remove(path)
    finally:
        pass..
Код

будет работать даже без "try.. finally", но он будет создавать проблему, если файл был случайно удален. изменено: перемещение соответствия модели внутри "try", чтобы оно не выдавало ошибку при регистрации пользователя Дайте мне знать, если есть какие-либо проблемы.

Ответ 8

Завершая ответ Криса Лоулора, попробовал это и работает.

from YOURAPP.settings import BASE_DIR

try:
    os.remove(BASE_DIR + user.userprofile.avatarURL)
except Exception as e:
    pass 

URL имеет шаблон /media/mypicture.jpg