首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django删除FileField

Django删除FileField
EN

Stack Overflow用户
提问于 2013-04-16 23:37:26
回答 9查看 76.7K关注 0票数 116

我正在用Django构建一个web应用程序。我有一个上传文件的模型,但我不能删除该文件。下面是我的代码:

代码语言:javascript
复制
class Song(models.Model):
    name = models.CharField(blank=True, max_length=100)
    author = models.ForeignKey(User, to_field='id', related_name="id_user2")
    song = models.FileField(upload_to='/songs/')
    image = models.ImageField(upload_to='/pictures/', blank=True)
    date_upload = models.DateField(auto_now_add=True)

    def delete(self, *args, **kwargs):
        # You have to prepare what you need before delete the model
        storage, path = self.song.storage, self.song.path
        # Delete the model before the file
        super(Song, self).delete(*args, **kwargs)
        # Delete the file after the model
        storage.delete(path)

然后,在python manage.py shell中,我这样做:

代码语言:javascript
复制
song = Song.objects.get(pk=1)
song.delete()

它会从数据库中删除记录,但不会删除服务器上的文件。我还能尝试什么呢?

谢谢!

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2013-04-16 23:50:57

在Django 1.3之前,当您删除相应的模型实例时,文件会自动从文件系统中删除。您可能正在使用较新的Django版本,因此您必须自己实现从文件系统中删除文件。

基于信号的简单样本

我在撰写本文时选择的方法是post_deletepre_save信号的混合,这使得每当删除相应的模型或更改其文件时,过时的文件都会被删除。

基于一个假设的MediaFile模型:

代码语言:javascript
复制
import os
import uuid

from django.db import models
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _


class MediaFile(models.Model):
    file = models.FileField(_("file"),
        upload_to=lambda instance, filename: str(uuid.uuid4()))


# These two auto-delete files from filesystem when they are unneeded:

@receiver(models.signals.post_delete, sender=MediaFile)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    """
    Deletes file from filesystem
    when corresponding `MediaFile` object is deleted.
    """
    if instance.file:
        if os.path.isfile(instance.file.path):
            os.remove(instance.file.path)

@receiver(models.signals.pre_save, sender=MediaFile)
def auto_delete_file_on_change(sender, instance, **kwargs):
    """
    Deletes old file from filesystem
    when corresponding `MediaFile` object is updated
    with new file.
    """
    if not instance.pk:
        return False

    try:
        old_file = MediaFile.objects.get(pk=instance.pk).file
    except MediaFile.DoesNotExist:
        return False

    new_file = instance.file
    if not old_file == new_file:
        if os.path.isfile(old_file.path):
            os.remove(old_file.path)

例如,

  • ,有一个possible data loss场景:如果你的save()方法调用恰好在一个被回滚的事务中,你的数据最终可能会引用一个不存在的文件。您可以考虑将文件删除逻辑包装到transaction.on_commit()中,就像transaction.on_commit(lambda: os.remove(old_file.path))as suggested in Mikhail’s comment一样。django-cleanupdoes something along those lines.

  • Edge案例:如果您的应用程序上传了一个新文件并将模型实例指向新文件,而没有调用save() (例如,通过批量更新QuerySet),则旧文件将继续存在,因为信号将不会运行。如果您使用传统的文件处理methods.

  • Coding样式,则不会发生这种情况:此示例使用file作为字段名,这不是一个好的样式,因为它与内置的file对象标识符冲突。

附录:定期清理

实际上,您可能还希望运行一个定期任务来处理孤立文件清理,以防运行时故障导致某些文件无法删除。考虑到这一点,您可能会完全摆脱信号处理程序,并使这样的任务成为处理不敏感数据和不太大的文件的机制。

但是,无论哪种方式,如果您正在处理敏感数据,最好是反复检查,确保您始终及时删除生产中的数据,以避免任何相关的责任。

另请参阅

Django 1.11模型字段引用中的

  • FieldFile.delete() (请注意,它描述了FieldFile类,但您可以直接在字段上调用.delete()FileField实例代理到相应的FieldFile实例,并且您可以像访问字段的方法一样访问它的方法)

请注意,删除模型时,不会删除相关文件。如果您需要清理孤立文件,则需要自己处理(例如,使用可以手动运行或计划通过cron定期运行的自定义管理命令)。

在早期的Django版本中,当包含FileField的模型实例被删除时,FileField自己也会从后端存储中删除该文件。这打开了几种数据丢失场景的大门,包括回滚事务和引用同一文件的不同模型上的字段。在Django1.3中,当一个模型被删除时,FileFielddelete()方法不会被调用。如果您需要清理孤立文件,则需要自己处理(例如,使用可以手动运行或计划通过cron定期运行的自定义管理命令)。

票数 169
EN

Stack Overflow用户

发布于 2015-03-11 20:14:47

试试django-cleanup,当你移除模型时,它会自动调用FileField上的delete方法。

代码语言:javascript
复制
pip install django-cleanup

settings.py

代码语言:javascript
复制
INSTALLED_APPS = (
     ...
    'django_cleanup.apps.CleanupConfig',
)
票数 92
EN

Stack Overflow用户

发布于 2017-02-03 16:37:49

在Django >= 1.10中,可以通过调用文件字段的.delete方法从文件系统中删除文件,如下图所示:

代码语言:javascript
复制
obj = Song.objects.get(pk=1)
obj.song.delete()
票数 47
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16041232

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档