Skip to content

Commit aea457b

Browse files
authored
Merge pull request #575 from autoantwort/feature/srcset
Make it possible to generate srcset with the thumbnail template tag
2 parents c4ed0bb + 973990d commit aea457b

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

docs/configuration.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ Settings
2424
The directory to which image files will be cached.
2525

2626

27+
.. attribute:: IMAGEKIT_DEFAULT_THUMBNAIL_SRCSET_SCALES
28+
29+
:default: ``None``
30+
31+
A list of scale factors, for example ``[2, 3]``. If specified, every
32+
``<img>`` generated by the ``thumbnail`` template tag will have a ``srcset``
33+
attribute with the given scales. To prevent this, set ``srcset=None``.
34+
35+
2736
.. attribute:: IMAGEKIT_DEFAULT_FILE_STORAGE
2837

2938
:default: ``None``

imagekit/templatetags/imagekit.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.utils.encoding import force_str
44
from django.utils.html import escape
55
from django.utils.safestring import mark_safe
6+
from django.conf import settings
67

78
from ..cachefiles import ImageCacheFile
89
from ..registry import generator_registry
@@ -13,6 +14,7 @@
1314
ASSIGNMENT_DELIMETER = 'as'
1415
HTML_ATTRS_DELIMITER = '--'
1516
DEFAULT_THUMBNAIL_GENERATOR = 'imagekit:thumbnail'
17+
default_thumbnail_srcset_scales = getattr(settings, 'IMAGEKIT_DEFAULT_THUMBNAIL_SRCSET_SCALES', None)
1618

1719

1820
def get_cachefile(context, generator_id, generator_kwargs, source=None):
@@ -126,11 +128,27 @@ def render(self, context):
126128
# recursion errors when anchor is set to a SafeString instance.
127129
# This converts the SafeString into a str instance.
128130
kwargs['anchor'] = kwargs['anchor'][:]
131+
srcset_scales = default_thumbnail_srcset_scales
132+
if "srcset" in kwargs:
133+
if kwargs['srcset'] is not None:
134+
srcset_scales = list(map(float, kwargs['srcset'].split()))
135+
else:
136+
srcset_scales = None
137+
kwargs.pop("srcset")
129138
if kwargs.get('format'):
130139
kwargs['format'] = kwargs['format'][:]
131140
generator = generator_registry.get(generator_id, **kwargs)
132141

133142
file = ImageCacheFile(generator)
143+
srcset = []
144+
if srcset_scales:
145+
for scale in srcset_scales:
146+
scaled_kwargs = dict(kwargs)
147+
if scaled_kwargs.get("height"):
148+
scaled_kwargs["height"] = int(scaled_kwargs["height"] * scale)
149+
if scaled_kwargs.get("width"):
150+
scaled_kwargs["width"] = int(scaled_kwargs["width"] * scale)
151+
srcset.append(ImageCacheFile(generator_registry.get(generator_id, **scaled_kwargs)))
134152

135153
attrs = {k: v.resolve(context) for k, v in self._html_attrs.items()}
136154

@@ -140,6 +158,9 @@ def render(self, context):
140158
attrs.update(width=file.width, height=file.height)
141159

142160
attrs['src'] = file.url
161+
if len(srcset) > 0:
162+
attrs['srcset'] = f'{file.url} 1x , ' + ' , '.join(
163+
f'{entry[0].url} {entry[1]}x' for entry in zip(srcset, srcset_scales))
143164
attr_str = ' '.join('%s="%s"' % (escape(k), escape(v)) for k, v in
144165
attrs.items())
145166
return mark_safe('<img %s />' % attr_str)
@@ -245,7 +266,11 @@ def thumbnail(parser, token):
245266
246267
The thumbnail tag supports the "--" and "as" bits for adding html
247268
attributes and assigning to a variable, respectively. It also accepts the
248-
kwargs "format", "anchor", and "crop".
269+
kwargs "format", "srcset", "anchor", and "crop".
270+
271+
To use "srcset" (generating multiple thumbnails for different pixel densities) list the scale factors::
272+
273+
{% thumbnail '100x100' mymodel.profile_image srcset='2 3' %}
249274
250275
To use "smart cropping" (the ``SmartResize`` processor)::
251276

tests/test_thumbnail_tag.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pytest
2+
import re
23
from django.template import TemplateSyntaxError
34

45
from . import imagegenerators # noqa
@@ -89,6 +90,14 @@ def test_alternate_generator():
8990
assert html == '1'
9091

9192

93+
def test_srcset_arg():
94+
ttag = r"""{% thumbnail '100x' img srcset="1.5 2" %}"""
95+
clear_imagekit_cache()
96+
html = render_tag(ttag)
97+
srcset_regex = re.compile('srcset=".* 1x ,.* 1\\.5x ,.* 2.0x"')
98+
assert srcset_regex.search(html) is not None
99+
100+
92101
def test_alternate_format():
93102
ttag = r"""{% thumbnail '100x' img format='webp' as th %}{{ th.url }}"""
94103
clear_imagekit_cache()

0 commit comments

Comments
 (0)