ImageField在使用os.unlink()时无法删除文件

0 投票
1 回答
715 浏览
提问于 2025-04-16 16:46

我有一个这样的模型:

class UserProfile(models.Model):
    """(UserProfile description)"""
    user = models.ForeignKey(User)
    image = models.ImageField(upload_to=upload_to)

    def save(self):
        os.unlink(self.image.path)
        super(UserProfile, self).save()

这个脚本在执行 unlink() 方法时出错,提示找不到文件。有没有什么想法?

错误信息是:

(2, '没有这样的文件或目录')

1 个回答

2

你需要更具体的调试。此外,你写的代码可能会导致错误。我不太确定,但我不会惊讶如果在创建UserProfile记录之前,UserProfile.image的值没有被设置。

所以我会这样重写你的代码:

class UserProfile(models.Model):
    user = models.ForeignKey(User)
    image = models.ImageField(upload_to=upload_to)

    def save(self):
        if self.image.path:
            try:
                os.unlink(self.image.path)
            except Exception, inst:
                raise Exception("Unable to delete %s. Error: %s" % (self.image.path, inst))
        super(UserProfile, self).save()

更新

现在想想,确实有道理,一旦你调用了save,新的信息就已经在self.image里了。如果你的目标是在保存新图片时删除旧图片,你需要使用Django中的pre_save信号来在保存图片之前获取旧记录(也就是旧图片的路径)。理论上,你可以把这个放在UserProfile模型的save方法里,但因为这只是一个不直接影响当前记录的附加操作,我建议把它分开处理。

下面是一个示例实现:

from django.db.models import signals
def delete_old_image(sender, instance, using=None):
    try:
        old_record = sender.objects.get(pk=instance.pk)
        os.unlink(old_record.image.path)
    except sender.DoesNotExist:
        pass
signals.pre_save.connect(delete_old_image, sender=UserProfile)

你可以把这个放在你的models.py文件里。

撰写回答