如何在 django 中为 sorl-thumbnail 设计清理任务?

Posted

技术标签:

【中文标题】如何在 django 中为 sorl-thumbnail 设计清理任务?【英文标题】:How to design cleanup tasks for sorl-thumbnail in django? 【发布时间】:2013-12-26 07:30:02 【问题描述】:

我正在使用 sorl-thumbnail,它提供给定图像的缓存缩略图。 我想在原始图像更改或被删除时删除生成的拇指。 我知道 sorl-thumbnail 为这种情况提供了删除方法,但是..

不会通过 django-admin 触发 可能是争用条件的坏原因 当使用像 redis 这样的 kv 存储时 - 所有数据(文件连接)都可能消失(例如重新启动)

更适合的是 sorl cleanup 管理命令。此命令将删除原始链接断开的 kv 条目和相关的物理拇指。但是如果我的kv存储不完整怎么办?我不想到处乱扔死文件。

我想到了一个 celery 任务,它会触发清理命令并另外检查所有缓存的文件,但不知道如何设计。

检测和清理这些混乱的最佳方法是什么?

【问题讨论】:

【参考方案1】:

您可以向模型添加方法 clear_thumbnails()。在 clear_thumbnails() 中,您使用 sorl-thumbnail 中的 delete function 删除现有缩略图。如果下次使用% thumbnail % 模板标签渲染视图,则会创建新的缩略图。

现在您添加一个函数,该函数在调用与缩略图相关的模型的pre_save signal 时运行。在此函数中,您只需调用 clear_thumbnails()

使用这种方法,当您在 Django admin 中更改模型时,缩略图也会被删除。 (你也可以捕捉到 pre_delete 信号)

类似这样的:

## models.py ##
from django.db import models
from sorl.thumbnail import delete as delete_thumbnails

class Route(models.Model):
    ...
    def clear_thumbnails(self):
        delete_thumbnails(self.image)

## receivers.py ##
from django.db.models.signals import pre_save

@receiver(pre_save, sender=YourModel)
def receive_yourmodel_pre_save(sender, **kwargs):
    sender.clear_thumbnails()

现在您有了一个模型,该模型可以在模型更改时删除缩略图。 (如果图像字段发生更改,则如果 pre_save 或 post_save 信号,也许您应该在接收器中添加检查,并且仅在发生这种情况时删除缩略图)

如果你有很多缩略图,那么 sorl-thumbnails 的管理命令就没用了。我在 sorl-thumbnails 键值存储中有几百万个条目,并且管理命令永远不会完成。

我最终编写了自己的小清理脚本,它比 sorl-thumbnails 提供的更好,因为它不使用太多内存并且还显示了一个进步。像这样的:

function clean_thumbnails(self):
    max_id = MyModel.objects.all().order_by('-pk')[0].pk

    for id in xrange(max_id, 0, -1):
        try:
            my_obj = MyModel.objects.get(pk=id)
            my_obj.clear_thumbnails()
            print "processed object with id %s" % id
        except MyModel.DoesNotExist:
            pass

我将此清理脚本设置为RunScript as defined the Django extensions。查看 Django 扩展和 RunScript 部分。这很方便。

希望这会有所帮助。

【讨论】:

以上是关于如何在 django 中为 sorl-thumbnail 设计清理任务?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 中为分组选项设置默认值

如何在 django 中为分组选项设置默认值

如何在 django 中为选项标签添加属性?

如何在 django 中为选项标签添加属性?

如何在 Django 中为页面添加书签?

django + celery - 如何在我的 django 应用程序中为 celery 设置 crontab 计划?