簡體   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