129 votes

Django supprime FileField

Je suis en train de construire une application web en Django. J'ai un modèle qui télécharge un fichier, mais je ne peux pas supprimer le fichier. Voici mon 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)

Ensuite, en python manage.py shell Je fais ça :

song = Song.objects.get(pk=1)
song.delete()

Il supprime l'enregistrement de la base de données mais pas le fichier sur le serveur. Que puis-je essayer d'autre ?

Merci !

5voto

Voici une application qui supprimera les anciens fichiers chaque fois qu'un modèle est supprimé ou qu'un nouveau fichier est téléchargé : django-smartfields

from django.db import models
from smartfields import fields

class Song(models.Model):
    song = fields.FileField(upload_to='/songs/')
    image = fields.ImageField(upload_to='/pictures/', blank=True)

3voto

Java Developer Points 172

@Anton Strogonoff

Il me manque quelque chose dans le code lorsqu'un fichier change, si vous créez un nouveau fichier, cela génère une erreur, parce que le nouveau fichier n'a pas trouvé de chemin. J'ai modifié le code de la fonction et ajouté une phrase try/except et ça marche bien.

@receiver(models.signals.pre_save, sender=MediaFile)
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 = MediaFile.objects.get(pk=instance.pk).file
    except MediaFile.DoesNotExist:
        return False

    new_file = instance.file
    if not old_file == new_file:
        try:
            if os.path.isfile(old_file.path):
                os.remove(old_file.path)
        except Exception:
            return False

0voto

LanfeaR Points 136

Ce code sera exécuté chaque fois que je téléchargerai une nouvelle image (champ logo) et vérifiera si un logo existe déjà ; si c'est le cas, il le fermera et le supprimera du disque. La même procédure pourrait bien sûr être faite en fonction récepteur. J'espère que cela vous aidera.

 #  Returns the file path with a folder named by the company under /media/uploads
    def logo_file_path(instance, filename):
        company_instance = Company.objects.get(pk=instance.pk)
        if company_instance.logo:
            logo = company_instance.logo
            if logo.file:
                if os.path.isfile(logo.path):
                    logo.file.close()
                    os.remove(logo.path)

        return 'uploads/{0}/{1}'.format(instance.name.lower(), filename)

    class Company(models.Model):
        name = models.CharField(_("Company"), null=False, blank=False, unique=True, max_length=100) 
        logo = models.ImageField(upload_to=logo_file_path, default='')

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X