un1t/django-cleanup

Cleanup cached thumbnails

philippeluickx opened this issue · 18 comments

Not sure if this should be in scope, but what would be the best approach to order generated thumbnails?
I am using https://github.com/SmileyChris/easy-thumbnails

Thanks for a nice library!

un1t commented

I did not use easy-thumbnails, but as I see ThumbnailerFieldFile deletes thumbnails and cache within delete method. So I guess all should work.

class ThumbnailerFieldFile(FieldFile, Thumbnailer):

    ...

    def delete(self, *args, **kwargs):
        """
        Delete the image, along with any generated thumbnails.
        """
        source_cache = self.get_source_cache()
        # First, delete any related thumbnails.
        self.delete_thumbnails(source_cache)
        # Next, delete the source image.
        super(ThumbnailerFieldFile, self).delete(*args, **kwargs)
        # Finally, delete the source cache entry.
        if source_cache:
            source_cache.delete()

    ...
un1t commented

I get it, django-cleanup does not invoke delete method on filefield.
Alright, I will fix it.

un1t commented

Now it should work, please check code from master branch.

Hey!
Thanks for the swift reply, I am impressed!
I tried it out and not there for me yet. I was not super clear in my issue either, so more info:

In my setup, easy-thumbnails generates new images with a different naming. They are in the same location as the original file.
E.g.:
Original file:
WP_20150217_14_27_34_Pro.jpg
Cached files:
WP_20150217_14_27_34_Pro.jpg.300x300_q85_detail_upscale.jpg
WP_20150217_14_27_34_Pro.jpg.900x600_q85_box-128,0,1504,918_crop_detail_upscale.jpg
WP_20150217_14_27_34_Pro.jpg.900x600_q85_box-131,0,1510,918_crop_detail_upscale.jpg

After deleting the file through my interface, the original file is gone, but not the cached files.

un1t commented

Try now, easy-thumbnails is test covered.

Hmm, just trying it out on my server and now even the original file does not get deleted.
I am using django-storages for saving media files to S3, but at least previously the original file was deleted, so guessing that S3 should not be the issue here.
Anything I can do to help?

un1t commented

You could show how you use easy-thumbnails, or you can open tests and try to repeat you case.

Had a quick look at the code and on first sight I think the cached files are not deleted because they are not linked to any model directly. With easy-thumbnails, the model is saved in a thumbnail model, which does not have a FileField

https://github.com/SmileyChris/easy-thumbnails/blob/master/easy_thumbnails/models.py

class File(models.Model):
    storage_hash = models.CharField(max_length=40, db_index=True)
    name = models.CharField(max_length=255, db_index=True)
    modified = models.DateTimeField(default=timezone.now)

    objects = FileManager()

    class Meta:
        abstract = True
        unique_together = (('storage_hash', 'name'),)

    def __unicode__(self):
        return self.name


class Source(File):
    pass


class Thumbnail(File):
    source = models.ForeignKey(Source, related_name='thumbnails')

    class Meta:
        unique_together = (('storage_hash', 'name', 'source'),)

For reference, my implementation looks as follows:

class Picture(TimeStampedModel):
    """
    A generic class for pictures.
    """

    class Meta:
        abstract = True

    def __unicode__(self):
        return self.caption

    @property
    def get_absolute_image_url(self):
        return "{0}{1}".format(settings.MEDIA_URL, self.original_image.url)

    original_image = models.ImageField(
        'Image',
        upload_to='pictures/%Y/%m/%d',
        help_text="Optimal resolution 900x600"
    )

    title = models.CharField(
        max_length=50,
        blank=True,
    )

    caption = models.TextField(
        blank=True,
        validators=[MaxLengthValidator(140)],
    )


class CachedPicture(Picture):
    """
    A generic class for pictures.
    """

    class Meta:
        abstract = True

    # Using ImageKit to define resolution
    # for image to be used in carousel and as thumbnail.
    big_image = ImageSpecField(
        [SmartResize(900, 600)],
        source='original_image',
        format='JPEG',
        options={'quality': 75}
    )

    medium_image = ImageSpecField(
        [SmartResize(450, 300)],
        source='original_image',
        format='JPEG',
        options={'quality': 75}
    )
un1t commented

Don't see where do you use easy-thumbnail in your code. There is no ThumbnailerImageField or easy_thumbnails imports;
ThumbnailerImageField is based on ImageField which based on FileField. https://github.com/SmileyChris/easy-thumbnails/blob/master/easy_thumbnails/fields.py#L32

As I see you use ImageSpecField(from ImageKit) which is not based on FileField. So this is why django-cleanup does not work in your case.

You are absolutely right, sorry for that!

In this case: any plans for supporting imagekit?

un1t commented

Do you know how to delete these files? There are seems no delete method on ImageSpecField.

un1t commented

I think it is responsibility ImageKit contributors to implement delete method at first.

big_image = ImageSpecField(
    [SmartResize(900, 600)],
    source='original_image',
    format='JPEG',
    options={'quality': 75}
)

If you use just such simple image processing, you could try django-resized
Or you could use sorl-thumbnail or easy-thumbnail.

Thanks for the info, will have a look to that!
I will close this issue for now, let's see if imagekit manages to have a delete function somewhere in the future.

cnk commented

I am having the same problem as the original poster - but I am only using django's ImageField and easy-thumbnails. I put together a repo that demonstrates what I am seeing in my larger project. Many of my other problems have been misconfiguration or not recognizing the relevance of something in the docs. Can you tell me what I am missing?

https://github.com/cnk/easy_thumbnails_example

un1t commented

There are tests for easy-thumbnail, all should work, you could look at testapp
https://github.com/un1t/django-cleanup/tree/master/django_cleanup/testapp

cnk commented

For anyone else having the same problem, the aforementioned tests showed me that to get easy--thumbnails and django-cleanup to work nicely together, you need to define your image field as easy_thumbnails.fields.ThumbnailerImageField rather than Django's default ImageField. Once you do that, both work perfectly.

Thanks @un1t for this app which provides the missing behavior I expected from django itself.

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.