Django 2.x解决方案:
在Django 2中处理文件删除非常容易。我已经尝试过使用Django 2和SFTP Storage以及FTP STORAGE使用以下解决方案,并且我很确定它可以与实现该delete
方法的任何其他存储管理器一起使用。(delete
方法是storage
抽象方法之一。)
delete
以实例在删除自身之前删除其FileField的方式来覆盖模型的方法:
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()
正在运行Default Manager的删除查询。因此,如果您希望能够使用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
,但可以通过返回有关已删除对象或所需内容的信息来做得更好。