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

时间:2010-05-20 23:03:39

标签: python django django-models

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

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

9 个答案:

答案 0 :(得分:21)

使用django-cleanup

pip install django-cleanup

settings.py

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

)

答案 1 :(得分:14)

您必须手动删除旧图像。

图像的绝对路径存储在your_image_field.name中。所以你会做类似的事情:

os.remove(your_image_field.name)

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

答案 2 :(得分:13)

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

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)

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

答案 3 :(得分:12)

在更新模型实例之前,您可以使用FileField对象的delete方法。例如,如果FileFieldImageField被命名为photo且您的模型实例为profile,则以下内容将从磁盘中删除该文件

profile.photo.delete(False)

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

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

答案 4 :(得分:3)

这是一个默认删除孤立文件的应用: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()

答案 5 :(得分:2)

您可以在模型中定义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)

我的头像对每个人都有唯一的网址,例如“ 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 :(得分:1)

尝试一下,即使删除旧文件也可以使用

def logo_file(instance, filename):
this = business.objects.get(id=instance.id)
try:
    if this.logo is not None:
        path = "%s" % (this.logo)
        os.remove(path)
finally:
    pass..

代码即使没有“ try .. finally”也可以工作,但是如果不小心删除了文件,它将产生问题。 让我知道是否有任何问题。

答案 7 :(得分:0)

完成Chris Lawlor的回答,尝试并成功。

from YOURAPP.settings import BASE_DIR

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

URL的格式为/media/mypicture.jpg

答案 8 :(得分:0)

我所做的是保存旧图像的路径,如果表单有效,我会删除旧图像。

if request.method == 'POST':
        old_image = ""
        if request.user.profile.profile_picture:
            old_image = request.user.profile.profile_picture.path
        form = UpdateProfileForm(request.POST,request.FILES,instance = profile)
        if form.is_valid():
            if os.path.exists(old_image):
                os.remove(old_image)
        form.save()

有点乱,但你没有安装第三方或任何东西