How do I get Django Admin to delete files when I r

2019-01-03 22:39发布

I am using 1.2.5 with a standard ImageField and using the built-in storage backend. Files upload fine but when I remove an entry from admin the actual file on the server does not delete.

12条回答
爷、活的狠高调
2楼-- · 2019-01-03 23:13

You can receive the pre_delete or post_delete signal (see @toto_tico's comment below) and call the delete method on the FileField object, thus (in models.py):

class MyModel(models.Model):
    file = models.FileField()
    ...

# Receive the pre_delete signal and delete the file associated with the model instance.
from django.db.models.signals import pre_delete
from django.dispatch.dispatcher import receiver

@receiver(pre_delete, sender=MyModel)
def mymodel_delete(sender, instance, **kwargs):
    # Pass false so FileField doesn't save the model.
    instance.file.delete(False)
查看更多
别忘想泡老子
3楼-- · 2019-01-03 23:14

I may have a special case since I am using the upload_to option on my file field with dynamic directory names but the solution I found was to use os.rmdir.

In models:

import os

...

class Some_Model(models.Model):
     save_path = models.CharField(max_length=50)
     ...
     def delete(self, *args,**kwargs):
          os.rmdir(os.path.join(settings.MEDIA_ROOT, self.save_path)
          super(Some_Model,self).delete(*args, **kwargs)
查看更多
ゆ 、 Hurt°
4楼-- · 2019-01-03 23:16

This functionality will be removed in Django 1.3 so I wouldn't rely on it.

You could override the delete method of the model in question to delete the file before removing the entry from the database completely.

Edit:

Here is a quick example.

class MyModel(models.Model):

    self.somefile = models.FileField(...)

    def delete(self, *args, **kwargs):
        somefile.delete()

        super(MyModel, self).delete(*args, **kwargs)
查看更多
在下西门庆
5楼-- · 2019-01-03 23:19

Try django-cleanup

pip install django-cleanup

settings.py

INSTALLED_APPS = (
    ...
    'django_cleanup', # should go after your apps
)
查看更多
Deceive 欺骗
6楼-- · 2019-01-03 23:19

Maybe it's a little late. But the easiest way for me is to use a post_save signal. Just to remember that signals are excecuted even during a QuerySet delete process, but the [model].delete() method is not excecuted during the QuerySet delete process, so it's not the best option to override it.

core/models.py:

from django.db import models
from django.db.models.signals import post_delete
from core.signals import delete_image_slide
SLIDE1_IMGS = 'slide1_imgs/'

class Slide1(models.Model):
    title = models.CharField(max_length = 200)
    description = models.CharField(max_length = 200)
    image = models.ImageField(upload_to = SLIDE1_IMGS, null = True, blank = True)
    video_embed = models.TextField(null = True, blank = True)
    enabled = models.BooleanField(default = True)

"""---------------------------- SLIDE 1 -------------------------------------"""
post_delete.connect(delete_image_slide, Slide1)
"""--------------------------------------------------------------------------"""

core/signals.py

import os

def delete_image_slide(sender, **kwargs):
    slide = kwargs.get('instance')
    try:
        os.remove(slide.image.path)
    except:
        pass
查看更多
混吃等死
7楼-- · 2019-01-03 23:22

You may consider using a pre_delete or post_delete signal:

https://docs.djangoproject.com/en/dev/topics/signals/

Of course, the same reasons that FileField automatic deletion was removed also apply here. If you delete a file that is referenced somewhere else you will have problems.

In my case this seemed appropriate because I had a dedicated File model to manage all of my files.

Note: For some reason post_delete doesn't seem to work right. The file got deleted, but the database record stayed, which is completely the opposite of what I would expect, even under error conditions. pre_delete works fine though.

查看更多
登录 后发表回答