Several services exist to manage image transformations on behalf of the developer (imgix & cloudinary, to name two). However, these services rely on generating the appropriate markup at render time. In same cases this is a URL pointed to the their service, at other times this is a rendering the <img>
tag in a specific format.
Existing methods of image resizing perform this resize locally. Either online, or in an offline worker. It is also common to require the image sizes to be specified at the model level, whereas this should really only exist within the presentation logic.
The proposed solution is to provide a simple pluggable framework of image resizing backends, each of which is responsible for producing the necessary URLs & markup.
Examples:
<!-- Preferred, as it gives the backend greater flexibility -->
{% image author.profile_photo width="400" height="300" _alt="Example image" %}
<!-- Alternative where required -->
<img src="{% imageurl author.profile_photo width="400" height="300" %}" alt="Example image">
class Backend(Backend):
option_mapping = {
'width': 'w',
'height': 'h',
...
}
def __init__(self):
super(Backend, self).__init__()
self.api = an_image_service.client()
def normalise_options(self, user_options):
"""Convert user-provided options into a format this backend can use
By default this will apply the mapping specified by ``option_mapping``
"""
return super(Backend, self).normalise_options()
def get_url(self, django_file, options, attributes):
""" Return a URL to the provided django_file
Args:
django_file: A file object provided by the storage backend, of type
``django.core.files.File``
options: A dictionary of options provided by the user.
attributes: A dictionary of attributes to be rendered into
the HTML tag.
"""
url = self.api.get_url(django_file.url, **transformations)
return url
def get_html(self, django_file, options, attributes):
""" Render the HTML appropriate for displaying the image
"""
url = self.get_url(django_file, options, attributes)
if settings.IMAGES_RESPONSIVE:
html = '<div data-src="{url}"{attributes}>'
else:
html = '<img src="{url}"{attributes}>'
return html.format(
url=url,
attributes=self.make_html_attributes(attributes),
)