【问题标题】:Django delete unused media filesDjango 删除未使用的媒体文件
【发布时间】:2014-03-23 09:14:33
【问题描述】:

我有一个 django 项目,管理员可以在其中上传媒体。随着商品的销售,它们会从站点中删除,从而删除它们在 MySQL 数据库中的条目。但是,与该项目关联的图像仍保留在文件系统中。这不一定是坏行为——我不介意保留文件以防意外删除。我预见到的问题是从现在开始的两年后,由于存储空间有限,因为媒体文件夹中充斥着旧产品图片。

有没有人知道一种系统/编程的方式来对所有图像进行排序并将它们与相关的 MySQL 字段进行比较,从文件系统中删除任何不匹配的图像?在完美的世界中,我想象 django-admin 中的一个按钮,例如“清理未使用的媒体”,它执行能够执行此行为的 python 脚本。我将在这里分享我的最终解决方案,但我现在正在寻找的是任何有想法、了解资源或在某个时候自己做过这件事的人。

【问题讨论】:

    标签: python django django-admin


    【解决方案1】:

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

    pip install django-cleanup
    

    settings.py

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

    【讨论】:

    • 有时,我可能想在互联网上托管我的网站。我假设托管服务提供商的计算机拥有让我的网站在 Internet 上完美运行所需的一切。但是我如何确定他们是否拥有django_cleanup?如果他们不这样做,我该怎么办?
    【解决方案2】:

    django-unused-media 将通过管理命令帮助您清理旧的未使用的媒体。

    当您刚开始使用django-cleanup 并且已经有需要删除的文件时非常有用。 或者,如果您有需要从媒体目录中删除的缩略图。

    【讨论】:

      【解决方案3】:

      也许这有点晚了,但如果您还想了解更多关于删除可能出现的问题,here's an article 解释了如何以两种方式删除它们(使用代码 sn-ps)。

      有一个可以不时调用的管理命令,还有一个更“直接”的解决方案,使用信号。

      【讨论】:

      • 感谢您的链接
      【解决方案4】:

      您可以使用信号。比使用 os.remove() 在删除时清理相关文件。

      这样你的文件系统总是反映你的 db.无需点击按钮。

      【讨论】:

      • 重写删除方法还有其他问题。如果我在其他模型上有一个 ForeignKey,它有一个图像字段和 ON_CASCADE DELETE ...该图像不会自行删除。另一个问题是替换文件。当我更新一个 ImageField 时,旧文件仍保留在我的媒体文件夹中......从未使用的文件中清理媒体文件夹的正确方法是什么??
      • 不要使用删除方法。你看到了吗:stackoverflow.com/questions/4394194/… 和 github.com/un1t/django-cleanup
      • 如果您是 Django 新手,使用 os.remove() 可能听起来不错,但不是在部署时使用。我不是在敲这个答案;我经过惨痛的教训才学到这个。您通常不会在已部署的实例上保留用户上传。改为查看 django 的 default_storage.delete(<file name>)。
      【解决方案5】:

      以下是我目前使用 Django 1.7 的方式,需要从一开始就使用我不知道你是如何清理未引用的文件的。

      假设您有一个名为“汽车”的应用和一个名为“汽车”的模型。

      signals.py:

      # cars/signals.py
      
      from django.conf import settings
      from django.dispatch import receiver
      from django.db.models.signals import post_delete
      
      from cars.models import Car
      
      # By adding 'Car' as 'sender' argument we only receive signals from that model
      @receiver(post_delete, sender=Car)
      def on_delete(sender, **kwargs):
          instance = kwargs['instance']
          # ref is the name of the field file of the Car model
          # replace with name of your file field
          instance.ref.delete(save=False)
      

      apps.py:

      # cars/apps.py
      from django.apps import AppConfig
      
      class CarConfig(AppConfig):
          name = "cars"
          def ready(self):
              import cars.signals
      

      __init__.py:

      default_app_config = 'cars.apps.CarConfig'
      

      【讨论】:

      • 如果Car 对象更新它ref 字段,在这种情况下,它可能不再指向旧媒体文件,但您的信号不会捕获那个。
      • @WillemVanOnsem - 对不起,但我的回答太老了,我什至不记得我在哪个项目中使用了它。我不确定过去的 me 是知道任何警告:))
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-19
      • 1970-01-01
      • 2021-03-02
      • 1970-01-01
      • 2023-03-18
      • 2023-01-12
      相关资源
      最近更新 更多