首页 > 解决方案 > 覆盖 Django 中模型的批量删除

问题描述

我为模型编写了一个自定义delete方法。它似乎有两个警告。

  1. 当我进入 Django Admin 中的模型实例并单击删除时,该文件将从 AWS S3 存储桶中删除(这是首先覆盖该方法的目的)。模型本身也会被移除。

  2. 如果我通过“删除所选”批量功能删除,则文件会在 S3 中徘徊,但该实例会从该类型的实例列表中删除。

据我了解,在批量删除中,调用了不同的(查询集)方法。

我的问题是使单个和批量删除行为相同的最有效方法是什么?我应该尝试为此模型创建自定义管理器吗?

模型声明和删除方法:

from boto3.session import Session
from django.conf import settings

class Video(models.Model):
    title=models.CharField(max_length=500)
    description=models.TextField(default="")
    creation_date=models.DateTimeField(default=timezone.now)
    videofile=models.FileField(upload_to='videos/', null=True, verbose_name="")
    tags = TaggableManager()

    actions = ['delete']

    def __str__(self):
        return self.title + ": " + str(self.videofile)

    def delete(self, *args, **kwargs):
        session = Session (settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY)
        s3_resource = session.resource('s3')
        s3_bucket = s3_resource.Bucket(settings.AWS_STORAGE_BUCKET_NAME)

        file_path = "media/" + str(self.videofile)
        response = s3_bucket.delete_objects(
            Delete={
                'Objects': [
                    {
                        'Key': file_path
                    }
                ]
            })
        print(file_path)
        print(response)
        super(Video, self).delete(*args, **kwargs)

标签: djangodjango-modelsdjango-queryset

解决方案


您正在做徒劳的工作,因为批量删除不使用模型删除方法(文档

请记住,只要有可能,这将纯粹在 SQL 中执行,因此在此过程中不一定会调用单个对象实例的 delete() 方法。如果您在模型类上提供了自定义 delete() 方法并希望确保调用它,则需要“手动”删除该模型的实例(例如,通过迭代 QuerySet 并在每个对象单独)而不是使用 QuerySet 的批量 delete() 方法。

Django Admin删除选定对象不调用模型删除方法(与任何批量删除查询集相同)

来自 Django 管理操作文档

警告

出于效率原因,“删除选定对象”操作使用 QuerySet.delete(),它有一个重要的警告:您的模型的 delete() 方法将不会被调用。

如果您希望覆盖此行为,您可以覆盖 ModelAdmin.delete_queryset()或编写以您喜欢的方式执行删除的自定义操作 - 例如,通过为每个选定项目调用 Model.delete()。


推荐阅读