Arhn - архитектура программирования

Django - удалить файл с 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))

Ответы:


1

НАМНОГО безопаснее сделать 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)
21.01.2015
  • Дэвид, не могли бы вы уточнить часть своего ответа об очистке файлов S3 без ссылок? Как бы вы удалили файлы из S3, на которые нет ссылки в базе данных, сохранив файлы, на которые есть ссылки? 05.04.2017
  • @David Dehghan ... Меня также интересует последняя часть, как легко удалить файлы S3 без ссылок? 13.06.2017
  • Я не знаю какой-либо особой магии для удаления файлов S3 без ссылок. Вам нужно будет запустить пакетное задание, которое сбрасывает идентификаторы всех ваших файлов S3, а затем выполнить запрос, чтобы получить идентификаторы файлов БД и сравнить 2 списка. Пока мы просто проигнорировали эту проблему. Возможно, в S3 есть потерянные элементы, но в нашем случае стоимость достаточно дешевая, чтобы мы могли ее игнорировать. 14.06.2017

  • 2

    Вам нужно вызвать метод 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)
    
    11.12.2013
  • Я немного не хочу добавлять метод pre_delete, потому что, например, если что-то пойдет не так с удалением, я остаюсь с противоположной ситуацией, когда у меня есть файл, представленный в этой базе данных, но удаленный с сервера 11.12.2013
  • Хех, я неправильно прочитал ваш пост, подумал, что у него есть обработчик pre_delete. Что бы ни плавало на вашей лодке, я думаю. 11.12.2013
  • В любом случае, это не главное. Сработало как шарм, и я принимаю ваш ответ. Большое спасибо! 11.12.2013
  • Можно ли добавить пример того, как это работает в модели? Немного неясно, откуда берется этот экземпляр, где находится сигнальная функция и т. д. 10.04.2014
  • Добавлен полный пример обработчика сигнала. 11.04.2014
  • Из-за моего предыдущего комментария я изменил принятый ответ, так как он лучше отражает то, что я в итоге использовал. 01.08.2018

  • 3

    Попробуйте django-cleanup, он автоматически вызывает метод удаления в FileField при удалении модели.

    11.03.2015

    4

    У меня это сработало, удалив файлы как в БД, так и в 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. Удаление ссылки на файл в БД выполняется с помощью DeleteView, надеюсь, это кому-то поможет.

    09.05.2020
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..