Почему 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()