Cleanup Files (and Images) On Model Delete in Django

01 Jun · by Tim Kamanin · 1 min read

In Django, if your model has Filefield / Imagefield, when it's get deleted it doesn't delete attached files by default. To fix that you need to do two steps: 1) Add filecleanup function, that'll take care of deleting files attached to a model:

import os
from import default_storage
from django.db.models import FileField

def file_cleanup(sender, **kwargs):
File cleanup callback used to emulate the old delete
behavior using signals. Initially django deleted linked
files when an object containing a File/ImageField was deleted.

>>> from django.db.models.signals import post_delete
>>> post_delete.connect(file_cleanup, sender=MyModel, dispatch_uid="mymodel.file_cleanup")
for fieldname in sender._meta.get_all_field_names():
        field = sender._meta.get_field(fieldname)
        field = None
        if field and isinstance(field, FileField):
            inst = kwargs['instance']
            f = getattr(inst, fieldname)
            m = inst.__class__._default_manager
            if hasattr(f, 'path') and os.path.exists(f.path)\
            and not m.filter(**{'%s__exact' % fieldname: getattr(inst, fieldname)})\

2) In your, add post_delete signal to catch model deletion event:

from django.db import models
from django.db.models.signals import post_delete
from .utils import file_cleanup

... models code goes here ...

post_delete.connect(file_cleanup, sender=Image, dispatch_uid="gallery.image.file_cleanup")

And that's all. As you see on example above, my sender is Image model and when it's get deleted, it'll fire file_cleanup function that will take care of cleaning up files.


Required for comment verification


There is an app for that

Reply · 2 years, 10 months ago

I like your way of pretty much deleting every FileField. The way I'm doing it is with post_delete signals and pretty much specifying what field to delete instead of doing a for loop, for non noticeable faster performance haha. # Receive the pre_delete signal and delete the file associated with the model instance. from django.db.models.signals import post_delete from django.dispatch.dispatcher import receiver @receiver(post_delete, sender=Document) def mymodel_delete(sender, instance, **kwargs): if instance.public_file: instance.public_file.delete(False)

Reply · 3 years, 7 months ago