Почему on_delete в Django Rest Framework не работает так, как ожидалось для полей изображений и файлов?

Когда я удаляю родительскую таблицу с помощью Django rest через on_delete, она удаляет и дочернюю таблицу (из-за внешнего ключа), но содержимое изображений и файлов в дочерней таблице не удаляется. Я хочу удалить эти изображения и файлы также...! Как это сделать?

Мои таблицы 1:Группа 2:Posts Отношение один ко многим

Я удаляю таблицу Group следующим образом:

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

GroupsModel :

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 на ForeignKey - это то, что написано и управляется в схеме базы данных. Не Django удаляет дочернюю модель при удалении, а ваша база данных (MySQL, Postgres, ...), которая автоматически обнаруживает сбой на ForeignKey и выполняет каскадное действие (как контраинт).

models.ImageField и models.FileField - это (на уровне базы данных) просто CharField с местоположением в файловой системе вашего файла. База данных не может удалить файл, поэтому вы не можете делегировать это действие базе данных.

Если вы хотите автоматически удалить файл на модели .delete(), у вас есть несколько возможных стратегий :

  • Периодическая проверка того, что для каждого файла существует модель (если нет, удалите файл)
  • Переписать метод .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 не будет вызван в написанном вами наборе запросов, вам нужно удалить каждый экземпляр отдельно:

for instance in GroupsModel.objects.filter(id=py_data.get('group_id')):
   instance.delete()
Вернуться на верх