从许多记录中的FileField / ImageFields批量删除文件

时间:2013-06-24 07:43:34

标签: python django django-models

我有一个名为Picture的模型,它有一个ImageField字段picture_file

我正在使用post_delete信号从文件系统中删除文件,因为Picture被删除了:

def delete_picture(sender, **kwargs):
    picture_file = kwargs.get('instance')
    picture.picture_file.storage.delete(picture.picture_file.path)
post_delete.connect(delete_picture, Picture)

但批量删除不会触发删除后信号,因此对于bulk_deletes,我想收集所有路径并在一次操作中删除。这是可能的吗,在这种情况下,单个删除操作是否有益?

对于所有文件,存储方法应该是相同的,所以如果有批量文件删除命令/模块,我认为这是理想的吗?

2 个答案:

答案 0 :(得分:0)

批量删除的概念是有效的,所以它会更新的运行任何信号或其他方法。

您可以轻松地更改您的经理,在批量删除之前,您将获取所有要删除的路径,然后删除文件(或将此列表放入您的芹菜或cron工作者),然后从数据库中删除对象,如下所示:

class MyManager(models.Manager)
     def delete_with_files(self, **kwargs):
          qs = self.get_query_set().filter(**kwargs)
          files = list(qs.values_list('picture_file__path', flat=True))
          delete_all_files(files)
          qs.delete()

答案 1 :(得分:0)

嗯,这不是我正在寻找的答案,但这是我很满意的解决方案,直到有更好的方法出现:

而不是打电话:

Picture.objects.all().delete()

反过来,每行调用以下post_delete信号:

def delete_picture(sender, **kwargs):
    picture_file = kwargs.get('instance')
    picture.picture_file.storage.delete(picture.picture_file.path)

我改为断开信号然后在循环中删除文件,然后运行bulk_delete:

signals.post_delete.connect(delete_picture, sender=Picture)

pics = Picture.objects.all()
for pic in pics:
    signals.post_delete.connect(delete_picture_files, sender=PictureFile)
pics.delete()

使用timeit,在500次记录/文件的单次运行中,从34下降到1.6秒。