django 如何在更新图像字段时删除旧图像?

pcrecxhr  于 2023-01-31  发布在  Go
关注(0)|答案(9)|浏览(190)

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

imzjd6km

imzjd6km1#

使用django-cleanup

pip install django-cleanup

settings.py

INSTALLED_APPS = (
    ...
    'django_cleanup.apps.CleanupConfig', # should be placed after your apps

)
ejk8hzay

ejk8hzay2#

您必须手动删除旧映像。
映像的绝对路径存储在your_image_field.path中,因此您可以执行以下操作:

os.remove(your_image_field.path)

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

waxmsbnn

waxmsbnn3#

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

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)

它对我的网站很有效。这个问题也困扰着我,我不想一开始就做一个清理脚本,而不是做一个好的簿记。让我知道它是否有任何问题。

pobjuy32

pobjuy324#

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

profile.photo.delete(False)

要了解更多信息,请参阅django文档
https://docs.djangoproject.com/en/1.11/ref/models/fields/#django.db.models.fields.files.FieldFile.delete

chy5wohz

chy5wohz5#

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

我的头像有独特的网址为每个人喜欢“头像/ceb 47779 - 8833 - 4719 - 8711 - 6f4e5cabb2b2.png”。如果用户上传新图像与不同的扩展名,如jpg,delete_file_on_change_extension reciever删除旧图像,在使用网址“avatars/ceb47779-8833-4719-8711-6f4e5cabb2b2.jpg”保存新文件之前(在这种情况下)。如果用户上传新的图像与相同的扩展名django覆盖旧的图像存储(磁盘),因为图像路径是相同的。这在AWS S3 django-storage中运行良好。

x9ybnkn6

x9ybnkn66#

以下是默认情况下删除孤立文件的应用程序: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()
l0oc07j2

l0oc07j27#

试试这个,它将工作,即使旧文件被删除

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”,但它会产生问题,如果文件被意外删除。更改:移动模型匹配内“尝试”,所以它不会抛出任何错误,在用户注册让我知道,如果有任何问题。

p4rjhz4m

p4rjhz4m8#

完成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

pepwfjgg

pepwfjgg9#

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

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()

这是有点混乱,但你不安装第三方或任何东西

相关问题