更新ImageField时如何删除旧图像?

eos*_*s87 31 python django django-models

我正在使用Django创建一个股票照片网站,我的模型中有一个ImageField,问题是当用户更新图像字段时,原始图像文件不会从硬盘中删除.

如何在更新后删除旧图像?

un1*_*n1t 31

使用django-cleanup

pip install django-cleanup
Run Code Online (Sandbox Code Playgroud)

settings.py

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

)
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的选择 (2认同)
  • 这真太了不起了。顺便说一句,正如官方文档中所述,您应该将“django_cleanup.apps.CleanupConfig”放在您的 INSTALLED_APPS 列表中。 (2认同)

Chr*_*lor 16

您必须手动删除旧图像.

存储图像的绝对路径your_image_field.name.所以你要做的事情如下:

os.remove(your_image_field.name)
Run Code Online (Sandbox Code Playgroud)

但是,为方便起见,您可以使用关联的FieldFile对象,该对象可以轻松访问底层文件,并提供一些便捷方法.见http://docs.djangoproject.com/en/dev/ref/models/fields/#filefield-and-fieldfile


met*_*ics 15

在模型中使用此自定义保存方法:

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)
Run Code Online (Sandbox Code Playgroud)

它适用于我的网站.这个问题也困扰着我,我不想在一开始就制作一个清理脚本而不是好的簿记.如果有任何问题,请告诉我.

  • 您可能想要使用:'this.MyImageFieldName.delete(save = False)'因为我看到delete()以递归方式调用'MyModelName'模型的'save',小心...并使用print in test进行测试保存方法 (10认同)
  • 删除模型后删除文件也更好.如果因任何原因删除模型失败,则您不想丢失该文件. (2认同)

Nay*_*yan 12

在更新模型实例之前,可以使用FileFieldobject 的delete方法.例如,如果FileField或者ImageField命名为photo和您的模型实例一样profile,则以下内容将从磁盘中删除该文件

profile.photo.delete(False)
Run Code Online (Sandbox Code Playgroud)

有关更多说明,请参阅django doc

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


Qua*_*adX 8

您可以pre_save在模型中定义接收器:

@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)
Run Code Online (Sandbox Code Playgroud)

我的头像对每个人都有唯一的网址,例如“头像/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。