在 Django 中覆盖模型的批量删除

Overriding Bulk Delete of Models in Django

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

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

  2. 如果我通过 "Delete Selected" 批量功能删除,则该文件会保留在 S3 中,但该实例将从该类型的实例列表中删除。

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

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

模型声明和删除方法:

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)

您正在做无用功,因为批量删除不使用模型删除方法 (docs)

Keep in mind that this will, whenever possible, be executed purely in SQL, and so the delete() methods of individual object instances will not necessarily be called during the process. If you’ve provided a custom delete() method on a model class and want to ensure that it is called, you will need to “manually” delete instances of that model (e.g., by iterating over a QuerySet and calling delete() on each object individually) rather than using the bulk delete() method of a QuerySet.

Django Admin delete selected objects 不调用模型删除方法(与any bulk delete queryset)

From Django admin actions documentation

Warning

The “delete selected objects” action uses QuerySet.delete() for efficiency reasons, which has an important caveat: your model’s delete() method will not be called.

If you wish to override this behavior, you can override ModelAdmin.delete_queryset() or write a custom action which does deletion in your preferred manner – for example, by calling Model.delete() for each of the selected items.