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

6 python django sorl-thumbnail celery django-celery

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

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

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

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

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

Ant*_*ton 0

您可以将方法clear_thumbnails() 添加到模型中。在clear_thumbnails() 中,您使用sorl-thumbnail 中的删除函数来删除现有的缩略图。如果下次使用{% thumbnail %}模板标记呈现视图时,将创建新的缩略图。

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

通过这种方法,当您在 Django 管理中更改模型时,缩略图也会被删除。(您也可以捕获 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()
Run Code Online (Sandbox Code Playgroud)

现在您有了一个模型,只要模型发生更改,该模型就会删除缩略图。(如果图像字段发生更改,也许您应该在接收器中添加一个检查,检查 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
Run Code Online (Sandbox Code Playgroud)

我将此清理脚本设置为RunScript,如 Django 扩展所定义。查看 Django 扩展和 RunScript 部分。这非常方便。

希望这可以帮助。