respondcreate / django-versatileimagefield

A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for quickly creating new images from the one assigned to the field.
http://django-versatileimagefield.readthedocs.io/
MIT License
531 stars 88 forks source link

How to store filename returned by storage for sized images? #179

Open Routhinator opened 3 years ago

Routhinator commented 3 years ago

I recently adopted https://github.com/ecometrica/django-hashedfilenamestorage in my project for a number of reasons, but the major one being space savings and only uploading unique files to the S3 backed media storage.

The issue is that the filesystem returns the new filename as the return from save, and I need to try and get VersatileImageFieldWarmer to save these filenames for each sized image rendition to a meta field or something so it can be used for the filelocations returned by DRF.

Is there a way to accomplish this natively? Or will I need to override a class somewhere in my code for this usecase?

Routhinator commented 3 years ago

I worked around this problem for now by overriding the django-hashedfilenamestorage Storage class and overwriting their _get_content_name fuction with an exclusion for the __sized__ dir. While this works... I'm not sure it's a great solution. There may be storages where this isn't an option as well.

For anyone that hits this when using these two in combination, you can add this override for the mentioned fuction for now:

        def _get_content_name(self, name, content, chunk_size=None):
            """
            Gets the filename based on file content.
            :param name:
            :param content:
            :param chunk_size:
            :return:
            """
            dir_name, file_name = os.path.split(name)
            file_ext = os.path.splitext(file_name)[1].lower()
            if '__sized__' not in dir_name:
                file_root = self._compute_hash(content=content,
                                               chunk_size=chunk_size)
            else:
                file_root = file_name
            # file_ext includes the dot.
            return os.path.join(dir_name, file_root + file_ext)