Replacing a Django image doesn't delete original

Shige Abe picture Shige Abe · Dec 9, 2010 · Viewed 12.4k times · Source

In Django, if you have a ImageFile in a model, deleting will remove the associated file from disk as well as removing the record from the database.

Shouldn't replacing an image also remove the unneeded file from disk? Instead, I see that it keeps the original and adds the replacement.

Now deleting the object won't delete the original file only the replacement.

Are there any good strategies to doing this? I don't want to have a bunch of orphan files if my users replace their images frequently.

Answer

Geoffroy CALA picture Geoffroy CALA · Dec 1, 2011

The best strategy I've found is to make a custom save method in the model:

class Photo(models.Model):

    image = ImageField(...) # works with FileField also

    def save(self, *args, **kwargs):
        # delete old file when replacing by updating the file
        try:
            this = Photo.objects.get(id=self.id)
            if this.image != self.image:
                this.image.delete(save=False)
        except: pass # when new photo then we do nothing, normal case          
        super(Photo, self).save(*args, **kwargs)

And beware, as with the updating which doesn't delete the back end file, deleting an instance model (here Photo) will not delete the back-end file, not in Django 1.3 anyway, you'll have to add more custom code to do that (or regularly do some dirty cron job).

Finally test all your update/delete cases with your ForeignKey, ManytoMany and others relations to check if the back-end files are correctly deleted. Believe only what you test.