Question

I am deleting a related model from a form (nearly the same way as django admin), I have an item which has many images, image belongs to Item (ForeignKey). I have implemented a post_delete signal to delete thumbnails and the image when deleting the image/images from the form, the problem is that in the post_delete thumbnails are deleted but the image entry in the db remains:

# Auto-delete files from filesystem when they are unneeded:
@receiver(models.signals.post_delete, sender=ImageModel)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    """Deletes file from filesystem
    when corresponding `ImageModel` object is deleted.
    """
    if instance.imagefile:
        thumbmanager = get_thumbnailer(instance.imagefile)
        thumbmanager.delete()

If I add the following in the end, the image instance is also deleted (expected behavior):

# Auto-delete files from filesystem when they are unneeded:
@receiver(models.signals.post_delete, sender=ImageModel)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    """Deletes file from filesystem
    when corresponding `ImageModel` object is deleted.
    """
    if instance.imagefile:
        thumbmanager = get_thumbnailer(instance.imagefile)
        thumbmanager.delete()
        instance.delete()

Am I missing something? Shouldn't the post_delete signal be sent after deleting the instance? Why is the instance persisted in the db? I assume that this has to do with Queryset delete behavior, but I am sceptical to it since If I remove the signal then the instance of ImageModel is deleted (though thumbnails do remain in the database). Mind that the model uses the django build in ImageField field, and not easy thumbnails provided fields:

class ImageModel(models.Model):
    ...
    imagefile = models.ImageField(upload_to="properties/%m/%Y")
    item = models.ForeignKey('app.ItemModel', related_name='images')
    ...

The above solution (instance.delete()) is working with no problems, just curious about the behavior.

Was it helpful?

Solution 2

Ok got it working with adding delete(save=False):

# These two auto-delete files from filesystem when they are unneeded:
@receiver(models.signals.post_delete, sender=ImageModel)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    """Deletes file from filesystem
    when corresponding `ImageModel` object is deleted.
    """
    if instance.imagefile:
        thumbmanager = get_thumbnailer(instance.imagefile)
        thumbmanager.delete(save=False)

OTHER TIPS

You can also use django-cleanup, it automatically invokes delete method on FileField when you remove model.

pip install django-cleanup

settings.py

INSTALLED_APPS = (
     ...
    'django_cleanup', # should go after your apps
)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top