Walk through these actions to add the responsive images:
- To create thumbnail images dynamically, we will use the sorl-thumbnail app. Install this either by directly invoking pip in a virtual environment, or through the requirements in a Docker project:
# requirements.txt or base.txt
# ...
sorl-thumbnail~=12.4.0
It will also need to be added to the INSTALLED_APPS:
# settings.py or config/base.py
INSTALLED_APPS = [
# ...
'sorl.thumbnail',
]
- Once sorl_thumbnail is installed, make sure to migrate your database to add necessary schema for full thumbnail support.
- Then, add an image field to the Location model, as follows:
# locations/models.py
import os
# ...
def upload_to(instance, filename):
base, ext = os.path.splitext(filename)
return f"locations/{instance.slug}{ext.lower()}"
class Location(models.Model):
# ...
image = models.ImageField(null=True,
upload_to=upload_to)
# ...
- Update the admin.py as shown in the following code to expose the image field, and then make/run migrations for the locations app:
# locations/admin.py
class LocationAdmin(admin.ModelAdmin):
# ...
def get_fieldsets(self, request, obj=None):
map_html = render_to_string("admin/includes/map.html")
fieldsets = [
# ...
(_("Image"), {"fields": ("image",)}),
]
return fieldsets
- Next we need to update the detail template to include the new image, when one exists:
{# templates/locations/location_detail.html #}
{% extends "base.html" %}
{% load static thumbnail %}
{% get_media_prefix as MEDIA_URL %}
{% block extrahead %}
<script src="{% static 'site/js/lib/picturefill.min.js' %}"></script>
{% endblock %}
{% block content %}
<h2 class="map-title">{{ location.title }}</h2>
{% if location.image %}
<picture>
{% thumbnail location.image "480" as mobile_image %}
<source media="(max-width: 480px)"
srcset="{{ mobile_image.url }}">
{% endthumbnail %}
{% thumbnail location.image "768" as tablet_image_sm %}
<source media="(max-width: 768px)"
srcset="{{ tablet_image_sm.url }}">
{% endthumbnail %}
{% thumbnail location.image "1024" as tablet_image_lg %}
<source media="(max-width: 1024px)"
srcset="{{ tablet_image_lg.url }}">
{% endthumbnail %}
<img src="{{ MEDIA_URL }}{{ location.image.url }}"
alt="{{ location.title }} image">
</picture>
{% endif %}
{# ... #}
{% endblock %}
{# ... #}
- As we can see from the previous code, we need to add a picturefill.min.js file to our static content, which can be downloaded following the instructions at https://scottjehl.github.io/picturefill/. Since this is a third-party script, it has been placed under a lib/ subdirectory in the static/site/js/ area.
- Update the styles to make sure the image size is fluid:
# static/site/css/style.css
picture img {
width: 100%;
}
- Finally, after migrating the location app to add the img field to the database, add a location with an image via the admin, or update an existing location if you prefer.