Решение 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
, но вы можете сделать это лучше, вернув что-нибудь об удаленных вами объектах или о том, что вы хотите.