为什么 Django Rest Framework on_delete 在图像和文件字段上无法按预期工作?

Why on_delete of Django Rest Framework not work as expected on Image and File Fields?

当我使用 Django rest 删除父项 table 时,由于 on_delete 它删除了子项 table 也(由于外键)但是子项的图像和文件内容table 未删除。 我也想删除那些图像和文件..! 怎么做..?

我的table 1:Group 2:Posts 一对多关系

我删除群组table如下:

GroupsModel.objects.filter(id=py_data.get('group_id')).delete()

群组模型:

class GroupsModel(models.Model):
    group_name = models.CharField(max_length=20, unique=True)
    group_description = models.CharField(max_length=50)
    group_joining_link = models.CharField(max_length=50, default='', unique=True)
    user_id = models.ManyToManyField(UserModel, through='UserModelGroupsModel', related_name='u_g')

    class Meta:
        db_table = 'groups'

GroupPostsModel:

class GroupPostsModel(models.Model):
    post_text = models.CharField(max_length=1000)
    post_type = models.CharField(max_length=20)
    image = models.ImageField(blank=True, null=True, upload_to='post_images/')
    document = models.FileField(blank=True,null=True, upload_to='post_documents/')
    likes = models.IntegerField(default=0)
    time_stamp = models.DateTimeField(auto_now=True)
    group = models.ForeignKey(GroupsModel, on_delete=models.CASCADE)
    user = models.ForeignKey(UserModel, on_delete=models.CASCADE)

    class Meta:
        db_table = 'group_posts'

我也想自动删除图片和文档文件。

on_delete=models.CASCADE on a ForeignKey 是在数据库模式上编写和管理的内容。在删除时删除子模型的不是 Django,而是您的数据库(MySQL、Postgres 等)自动检测外键故障并执行级联操作(如约束)。

models.ImageFieldmodels.FileField(在数据库级别)只是一个 CharField,其中包含文件在文件系统上的位置。数据库无法删除文件,因此您不能将此操作委托给数据库。

如果您想自动删除模型 .delete() 上的文件,您有多种可能的策略:

  • 定期检查每个文件是否存在模型(如果不存在,请删除文件)
  • 覆盖 GroupPostsModel.delete() 方法(但只有当您在模型的实例上调用 .delete() 时它才会起作用,而不是在查询集上,就像在您的示例中那样)
  • 在删除端点上添加删除功能。

删除实例时,不会删除引用的文件,因为 ImageField/FileField 只是对文件的引用。您可以覆盖模型的 delete 方法:

import os

class GroupPostsModel(models.Model):
    post_text = models.CharField(max_length=1000)
    post_type = models.CharField(max_length=20)
    image = models.ImageField(blank=True, null=True, upload_to='post_images/')
    document = models.FileField(blank=True,null=True, upload_to='post_documents/')
    likes = models.IntegerField(default=0)
    time_stamp = models.DateTimeField(auto_now=True)
    group = models.ForeignKey(GroupsModel, on_delete=models.CASCADE)
    user = models.ForeignKey(UserModel, on_delete=models.CASCADE)
    
    def delete(self):
       if self.image:
          if os.path.isfile(self.image.path):
             os.remove(self.image.path)

       if self.document:
          if os.path.isfile(self.document.path):
             os.remove(self.document.path)
       
       super().delete()

    class Meta:
        db_table = 'group_posts'

delete方法不会在你写的queryset中被调用,你需要单独删除每个实例:

for instance in GroupsModel.objects.filter(id=py_data.get('group_id')):
   instance.delete()