Skip to content

Instantly share code, notes, and snippets.

@adamcharnock
Last active February 17, 2016 08:30
Show Gist options
  • Save adamcharnock/991454274cda8a66107a to your computer and use it in GitHub Desktop.
Save adamcharnock/991454274cda8a66107a to your computer and use it in GitHub Desktop.
Plan: Django Image Backend

Plan: Django Image Backend

Motivation

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.

Solution

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">

Example backend

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),
            )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment