Python Django-从AmazonS3删除文件
我有一个问题,删除一个对象形式的管理员不会删除与之相关的文件。经过一些研究,我决定在模型中实现post_delete。 由于某些原因,我无法让s3删除该文件,即使在搜索了大量的指南和代码片段之后,也许这里有人知道。 我使用django 1.5和boto。 以下是我的模型代码:Python Django-从AmazonS3删除文件,python,django,file,amazon-web-services,amazon-s3,Python,Django,File,Amazon Web Services,Amazon S3,我有一个问题,删除一个对象形式的管理员不会删除与之相关的文件。经过一些研究,我决定在模型中实现post_delete。 由于某些原因,我无法让s3删除该文件,即使在搜索了大量的指南和代码片段之后,也许这里有人知道。 我使用django 1.5和boto。 以下是我的模型代码: from django.db import models from django.contrib.auth.models import User from fileservice.formatChecker import
from django.db import models
from django.contrib.auth.models import User
from fileservice.formatChecker import ContentTypeRestrictedFileField
from south.modelsinspector import add_introspection_rules
import os
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
from django.core.files.storage import default_storage as storage
add_introspection_rules([
(
[ContentTypeRestrictedFileField], # Class(es) these apply to
[], # Positional arguments (not used)
{ # Keyword argument
"content_types": ["content_types", {}],
"max_upload_size": ["max_upload_size", {}]
},
),
], ["^fileservice\.formatChecker\.ContentTypeRestrictedFileField"])
class Contentfile(models.Model):
content = ContentTypeRestrictedFileField(upload_to='uploads/', content_types=['video/mp4', 'application/pdf', 'image/gif', 'image/jpeg', 'image/png'],max_upload_size=5242880,blank=True, null=True, help_text='Upload a file to add it to the content the app displayes')
created_at = models.DateTimeField(auto_now_add=True, editable=False)
updated_at = models.DateTimeField(auto_now=True, editable=False)
title = models.CharField(max_length=255, unique=True)
file_type = models.CharField(max_length=5)
published = models.BooleanField(default=True)
file_owner = models.ForeignKey(User, related_name='Contentfiles')
class Meta:
ordering = ["title"]
def __unicode__(self):
return self.title
def save(self, *args, **kwargs):
file_name = os.path.basename(self.content.name)
self.file_type = file_name.split('.')[-1]
self.title = file_name.split('.')[0]
self.published = True
super(Contentfile, self).save(*args, **kwargs)
@receiver(models.signals.post_delete, sender=Contentfile)
def auto_delete_file_on_delete(sender, instance, **kwargs):
"""Deletes file from filesystem
when corresponding `MediaFile` object is deleted.
"""
if instance.content:
if os.path.isfile(storage.open(instance.content.path)):
os.remove(storage.open(instance.content.path))
@receiver(models.signals.pre_save, sender=Contentfile)
def auto_delete_file_on_change(sender, instance, **kwargs):
"""Deletes file from filesystem
when corresponding `MediaFile` object is changed.
"""
if not instance.pk:
return False
try:
old_file = Contentfile.objects.get(pk=instance.pk).content
except Conentfile.DoesNotExist:
return False
new_file = instance.content
if not old_file == new_file:
if os.path.isfile(storage.open(old_file.path)):
os.remove(storage.open(old_file.path))
您需要调用delete()
方法来删除S3中的文件。在您的情况下,在您称之为的位置添加一个信号:
@receiver(models.signals.pre_delete, sender=ContentFile)
def remove_file_from_s3(sender, instance, using):
instance.content.delete(save=False)
做post_delete要安全得多。如果出现问题,您将开始丢失S3文件,您不会注意到它,因为您的DB记录是完整的。post_delete将更安全,因为在删除数据库记录后,S3 delete操作失败的可能性更小。此外,即使文件删除失败,您将留下一堆未引用的S3文件,这些文件是无害的,可以轻松清理
@receiver(models.signals.post_delete, sender=Picture)
def remove_file_from_s3(sender, instance, using, **kwargs):
instance.img.delete(save=False)
尝试一下,当您删除模型时,它会自动调用FileField上的delete方法。通过删除DB和AWS S3中的文件,这对我很有效
from django.db import models
from django.dispatch import receiver
from django.views import generic
from project.models import ContentFile
from django.contrib.auth.mixins import LoginRequiredMixin,UserPassesTestMixin
class DeleteFileView(LoginRequiredMixin,UserPassesTestMixin,generic.DeleteView):
model = ContentFile
template_name = 'file-delete.html'
success_url = 'redirect-to'
#Check if the owner of the file is the one trying to delete a file
def test_func(self):
obj = self.get_object()
if obj.user == self.request.user:
return True
return False
#This code does magic for S3 file deletion
@receiver(models.signals.pre_delete, sender=ContentFile)
def remove_file_from_s3(sender, instance, using, **kwargs):
instance.image_file.delete(save=False)
我正在使用
pre_delete
您可以检查数据库中的.File reference删除是由DeleteView完成的,我希望这对某些人有所帮助我不太愿意添加pre_delete方法,因为例如,如果删除出现任何问题,我仍然使用相反的情况,我在数据库中有一个文件,但是被从服务器上删除了。嘿,我误读了你的文章,以为它有一个pre_delete处理程序。我想无论什么能让你的船浮起来。不管怎样,这不是重点。工作很有魅力,我接受你的回答。非常感谢你!是否可以在模型中添加一个示例来说明这是如何工作的?关于这个实例来自何处,信号函数在何处,还有一个完整的信号处理程序示例,我们还不太清楚。David,你能详细说明一下答案中的“清理未引用的S3文件”部分吗?如何从S3中删除数据库中没有引用的文件,同时保留引用的文件?@David Dehghan。。。我还对最后一部分感兴趣,如何轻松删除未引用的S3文件?我不知道删除未引用的S3文件有什么特别的魔力。您必须运行一个批处理作业来转储所有S3文件的ID,然后运行一个查询来获取DB文件ID并比较这两个列表。现在我们只是忽略了这个问题。我们可能在S3中有孤立项,但在我们的例子中,成本足够便宜,我们可以忽略它。