繁体   English   中英

Django - 从亚马逊 S3 中删除文件

[英]Django - Delete file from 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 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))

执行 post_delete 更安全。 如果出现问题,您将开始丢失 S3 文件并且您不会注意到它,因为您的数据库记录完好无损。 post_delete 会更安全,因为在删除数据库记录后 S3 删除操作失败的可能性较小。 此外,即使文件删除失败,您也会留下一堆未引用的 S3 文件,这些文件是无害的,可以轻松清理。

@receiver(models.signals.post_delete, sender=Picture)
def remove_file_from_s3(sender, instance, using, **kwargs):
    instance.img.delete(save=False)

您需要调用FieldFile 的delete()方法来删除 S3 中的文件。 在您的情况下,在您调用它的地方添加一个pre_delete信号:

@receiver(models.signals.pre_delete, sender=ContentFile)
def remove_file_from_s3(sender, instance, using):
    instance.content.delete(save=False)

尝试django-cleanup ,它会在您删除模型时自动调用 FileField 上的 delete 方法。

通过删除数据库和 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你可以查看django 文档。DB 中的 文件引用删除是由 DeleteView 完成的,我希望这对某人有所帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM