Решение Django 2.x:
Обработать удаление файлов в Django 2 очень просто . Я пробовал следующее решение с использованием Django 2 и SFTP Storage, а также FTP STORAGE, и я почти уверен, что оно будет работать с любыми другими менеджерами хранилища, которые реализовали deleteметод. ( deleteметод - один из storageабстрактных методов.)
Переопределите deleteметод модели таким образом, чтобы экземпляр удалял свои FileFields перед удалением самого себя:
class Song(models.Model):
name = models.CharField(blank=True, max_length=100)
author = models.ForeignKey(User, to_field='id', related_name="id_user2")
song = models.FileField(upload_to='/songs/')
image = models.ImageField(upload_to='/pictures/', blank=True)
date_upload = models.DateField(auto_now_add=True)
def delete(self, using=None, keep_parents=False):
self.song.storage.delete(self.song.name)
self.image.storage.delete(self.song.name)
super().delete()
Для меня это работает довольно легко. Если вы хотите проверить, существует ли файл перед удалением, вы можете использовать storage.exists. Например self.song.storage.exists(self.song.name), вернет booleanпредставление, существует ли песня. Вот так это будет выглядеть:
def delete(self, using=None, keep_parents=False):
storage = self.song.storage
if storage.exists(self.song.name):
storage.delete(self.song.name)
if storage.exists(self.image.name):
storage.delete(self.song.name)
super().delete()
РЕДАКТИРОВАТЬ (в дополнение):
Как упоминал @HeyMan , при вызове этого решения Song.objects.all().delete()файлы не удаляются! Это происходит из-за того, что Song.objects.all().delete()выполняется запрос на удаление диспетчера по умолчанию . Поэтому, если вы хотите иметь возможность удалять файлы модели с помощью objectsметодов, вы должны написать и использовать Custom Manager (просто для переопределения его запроса на удаление):
class CustomManager(models.Manager):
def delete(self):
for obj in self.get_queryset():
obj.delete()
и для присвоения CustomManagerмодели вы должны инициализировать objectsвнутри своей модели:
class Song(models.Model):
name = models.CharField(blank=True, max_length=100)
author = models.ForeignKey(User, to_field='id', related_name="id_user2")
song = models.FileField(upload_to='/songs/')
image = models.ImageField(upload_to='/pictures/', blank=True)
date_upload = models.DateField(auto_now_add=True)
objects = CustomManager()
def delete(self, using=None, keep_parents=False):
self.song.storage.delete(self.song.name)
self.image.storage.delete(self.song.name)
super().delete()
Теперь вы можете использовать .delete()в конце любых objectsподзапросов. Я написал самое простое CustomManager, но вы можете сделать это лучше, вернув что-нибудь об удаленных вами объектах или о том, что вы хотите.