Рішення 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методів, ви повинні написати та використовувати користувальницький менеджер (лише для того, щоб замінити його запит на видалення):
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, але ви можете зробити це краще, повернувши щось про об’єкти, які ви видалили, або що завгодно.