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.image.name)
super().delete()
它对我来说很容易。如果要在删除之前检查文件是否存在,可以使用storage.exists
. 例如,如果歌曲存在,self.song.storage.exists(self.song.name)
将返回一个表示。boolean
所以它看起来像这样:
def delete(self, using=None, keep_parents=False):
# assuming that you use same storage for all files in this model:
storage = self.song.storage
if storage.exists(self.song.name):
storage.delete(self.song.name)
if storage.exists(self.image.name):
storage.delete(self.image.name)
super().delete()
编辑(另外):
正如@HeyMan提到的,使用此解决方案调用Song.objects.all().delete()
不会删除文件!发生这种情况是因为正在运行Default ManagerSong.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() # just add this line of code inside of your model
def delete(self, using=None, keep_parents=False):
self.song.storage.delete(self.song.name)
self.image.storage.delete(self.image.name)
super().delete()
现在您可以在任何子查询.delete()
的末尾使用。objects
我写了最简单的CustomManager
,但你可以通过返回一些关于你删除的对象或任何你想要的东西来做得更好。