Django删除FileField [英] Django 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,* args,*删除模型
存储,path = self.song.storage,self.song.path
#删除模型前的文件
super(Song,self).delete(* args,** kwargs)
#删除模型后的文件
storage.delete(path)
然后,在python manage.py shell中我这样做:
song = Song.objects.get(pk = 1)
song.delete()
它从数据库中删除但不从数据库中删除服务器上的文件。
我还可以尝试什么?
谢谢!
p>在Django 1.3之前,当您删除相应的模型实例时,文件将自动从文件系统中删除。您可能正在使用较新的Django版本,因此您必须自行实现从文件系统中删除该文件。
您可以通过以下几种方法之一:它正在使用 pre_delete
或 post_delete
信号。
示例
我现在选择的方法是混合使用 post_delete
和 pre_save
信号,这样就可以删除每当相应的模型被删除或更改文件时过时的文件。
根据假设的 MediaFile
模型:
导入os
import uuid
from django.db import models
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
class MediaFile(models.Model):
file = models.FileField(_(file),
upload_to = lambda实例,filename:str(uuid.uuid4 ))
#这两个文件系统在不需要时自动删除文件:
@receiver(models.signals.post_delete,sender = MediaFile)
def auto_delete_file_on_delete(sender,instance,** kwargs):
从文件系统
中删除文件,当对应的M ediaFile`对象被删除。
if instance.file:
如果os.path.isfile(instance.file.path):
os.remove(instance.file.path)
@receiver(models.signals.pre_save,sender = MediaFile)
def auto_delete_file_on_change(sender,instance,** kwargs):
删除旧文件文件系统
当对应的MediaFile对象被更新
与新文件。
if not instance.pk:
return False
try:
old_file = MediaFile.objects.get(pk = instance.pk ).file
除了MediaFile.DoesNotExist:
return False
new_file = instance.file
如果不是old_file == new_file:
如果os.path .isfile(old_file.path):
os.remove(old_file.path)
- 边缘案例:如果您的应用上传新文件,并将模型实例指向新文件,而不调用
save()
(例如批量更新QuerySet
),因为信号不会被运行,旧的文件将会继续存在,如果使用传统的文件处理方法,则不会发生。 - 编码风格:本示例使用
文件
作为字段名称,这不是一个好的风格,因为它与内置的文件
对象标识符
另请参见
-
FileField.delete()
(Django 1.11 model field reference)
请注意,当模型被删除时,相关文件不会被删除。如果您需要清理孤立的文件,那么您需要自己处理(例如,使用自定义管理命令,可以手动运行或通过例如cron定期运行)。
-
为什么Django不会自动删除文件:在Django 1.3的发行说明中的条目
在早期的Django版本中,当包含
FileField
的模型实例被删除时,FileField
本身也可以从后端存储中删除文件。这为几个数据丢失场景打开了大门,包括回滚事务和引用同一文件的不同模型上的字段。在Django 1.3中,当一个模型被删除时,不会调用FileField
的delete()
方法。如果您需要清理孤立的文件,您需要自己处理(例如,使用可以手动运行或定期运行的定制管理命令,例如通过cron定期运行)。
I'm building a web app in Django. I have a model that uploads a file, but I can not delete it. Here is my code:
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, *args, **kwargs):
# You have to prepare what you need before delete the model
storage, path = self.song.storage, self.song.path
# Delete the model before the file
super(Song, self).delete(*args, **kwargs)
# Delete the file after the model
storage.delete(path)
Then, in "python manage.py shell" I do this:
song = Song.objects.get(pk=1)
song.delete()
It deletes from database but not the file on server. What else can I try?
Thanks!
Before Django 1.3, the file was deleted from the filesystem automatically when you deleted the corresponding model instance. You are probably using a newer Django version, so you'll have to implement deleting the file from the filesystem yourself.
You can do that in a few ways, one of which is using a pre_delete
or post_delete
signal.
Example
My method of choice currently is a mix of post_delete
and pre_save
signals, which makes it so that obsolete files are deleted whenever corresponding models are deleted or have their files changed.
Based on a hypothetical MediaFile
model:
import os
import uuid
from django.db import models
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
class MediaFile(models.Model):
file = models.FileField(_("file"),
upload_to=lambda instance, filename: str(uuid.uuid4()))
# These two auto-delete files from filesystem when they are unneeded:
@receiver(models.signals.post_delete, sender=MediaFile)
def auto_delete_file_on_delete(sender, instance, **kwargs):
"""
Deletes file from filesystem
when corresponding `MediaFile` object is deleted.
"""
if instance.file:
if os.path.isfile(instance.file.path):
os.remove(instance.file.path)
@receiver(models.signals.pre_save, sender=MediaFile)
def auto_delete_file_on_change(sender, instance, **kwargs):
"""
Deletes old file from filesystem
when corresponding `MediaFile` object is updated
with new file.
"""
if not instance.pk:
return False
try:
old_file = MediaFile.objects.get(pk=instance.pk).file
except MediaFile.DoesNotExist:
return False
new_file = instance.file
if not old_file == new_file:
if os.path.isfile(old_file.path):
os.remove(old_file.path)
- Edge case: if your app uploads a new file and points model instance to the new file without calling
save()
(e.g. by bulk updating aQuerySet
), the old file will keep lying around because signals won’t be run. This doesn’t happen if you use conventional file handling methods. - I think one of the apps I’ve built has this code in production but nevertheless use at your own risk.
- Coding style: this example uses
file
as field name, which is not a good style because it clashes with the built-infile
object identifier.
See also
FileField.delete()
(Django 1.11 model field reference)Note that when a model is deleted, related files are not deleted. If you need to cleanup orphaned files, you’ll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via e.g. cron).
Why Django doesn’t delete files automatically: entry in release notes for Django 1.3
In earlier Django versions, when a model instance containing a
FileField
was deleted,FileField
took it upon itself to also delete the file from the backend storage. This opened the door to several data-loss scenarios, including rolled-back transactions and fields on different models referencing the same file. In Django 1.3, when a model is deleted theFileField
’sdelete()
method won’t be called. If you need cleanup of orphaned files, you’ll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via e.g. cron).
这篇关于Django删除FileField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!