当前位置: 首页 > 面试题库 >

Django删除FileField

颜志业
2023-03-14
问题内容

我正在Django中构建一个Web应用程序。我有一个上传文件的模型,但是无法删除它。这是我的代码:

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”中执行以下操作:

song = Song.objects.get(pk=1)
song.delete()

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


问题答案:

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

你可以通过几种方式做到这一点,其中一种方式是使用pre_deletepost_delete信号。


我目前选择的方法是post_deletepre_save信号的混合,这样可以确保在删除相应的模型或更改其文件时删除过时的文件。

基于一个假设MediaFile模型:

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)
  • 极端情况:如果你的应用程序上传了一个新文件并在未调用的情况下将模型实例指向该新文件save()(例如,通过批量更新QuerySet),则旧文件将继续散布,因为不会运行信号。如果使用常规文件处理方法,则不会发生这种情况。
  • 我认为我构建的其中一个应用程序已在生产中使用此代码,但使用时后果自负。
  • 编码样式:此示例将其file用作字段名称,但这不是一个好的样式,因为它与内置file对象标识符冲突。
    也可以看看

  • FieldFile.delete()在Django 1.11模型字段参考中(请注意,它描述了FieldFile该类,但你将.delete()直接在该字段上调用:FileField实例代理对应的FieldFile实例,并且可以像访问字段的方法一样访问其方法)

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

  • 为什么Django无法自动删除文件:Django 1.3发行说明中的​​条目

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

  • pre_delete仅使用信号的示例


 类似资料:
  • 问题内容: 我正在使用Django和Redis作为会话引擎(也是Celery,但这是其他东西)。它运行完美,我可以看到速度有所提高。 我有一个脚本,每分钟运行一次,以通过某些方法检查活动用户,如果该用户在最近一分钟内未处于活动状态,则该会话将被删除。这样做是为了满足客户的跟踪需求。 在我切换到Redis作为会话引擎之前,该脚本运行良好。实际上,该会话确实已从数据库中删除,但未从Redis中删除。我

  • 我知道有关于Django Rest框架的答案,但我找不到解决问题的方法。 我有一个应用程序,它具有身份验证和一些功能。我向它添加了一个新的应用程序,它使用Django Rest框架。我只想在此应用程序中使用库。我还想提出POST请求,我总是收到以下回复: 我有以下代码: 我希望在不影响当前应用程序的情况下添加API。因此,我的问题是,我如何才能禁用此应用程序的CSRF?

  • 问题内容: 案例我在/ notes / get / 1 /中,其中id =1,并且我在note.html中创建了“删除注释”链接。我需要它从数据库和应用程序中删除 当前 注释,然后重定向到/ notes / all。您能帮我处理def delete中的代码吗? models.py: urls.py: views.py: 问题答案: from django.shortcuts import get_

  • 我正在努力研究models.cascade语句的正确用法。我有两种型号的购物车和入门车。如果删除条目,则不会更新购物车条目上的删除。我已经通过管理界面检查过了。我的models.py如下所示:

  • 问题内容: 我做了一个模型,然后运行python manage.py syncdb。我认为在数据库中创建了一个表。然后我意识到我错误地创建了一个列,因此我更改了它,并运行了相同的命令,以为它将删除旧表并添加一个新表。 然后,我转到python manage.py shell,并尝试运行.objects.all(),但失败了,并说该列不存在。 我想清除旧表,然后再次运行syncdb,但是我不知道该怎

  • 问题内容: 有没有办法做到这一点? 注意:我没有,因此的课程不起作用。 问题答案: 你可以通过覆盖init方法来更改子类中的字段: