Add template tag for dynamic image url

Update documentation

Co-Authored-By: zerolab <dan@zerolab.org>
This commit is contained in:
Yannick Chabbert 2016-04-07 16:40:30 +02:00 committed by Mikalai Radchuk
parent ba5138e3fd
commit 515aa61943
7 changed files with 91 additions and 14 deletions

View file

@ -57,21 +57,10 @@ client over an API or used directly in the template.
One advantage of using dynamic image URLs in the template is that they do not
block the initial response while rendering like the ``{% image %}`` tag does.
.. code-block:: python
The ``generate_image_url`` function in ``wagtail.images.views.serve`` is a convenience
method to generate a dynamic image URL.
from django.urls import reverse
from wagtail.images.views.serve import generate_signature
def generate_image_url(image, filter_spec):
signature = generate_signature(image.id, filter_spec)
url = reverse('wagtailimages_serve', args=(signature, image.id, filter_spec))
# Append image's original filename to the URL (optional)
url += image.file.name[len('original_images/'):]
return url
And here's an example of this being used in a view:
Here's an example of this being used in a view:
.. code-block:: python
@ -92,6 +81,24 @@ Image operations can be chained by joining them with a ``|`` character:
})
In your templates:
.. code-block:: html+django
{% load wagtailimages_tags %}
...
<!-- Get the url for the image scaled to a width of 400 pixels: -->
{% image_url page.photo "width-400" %}
<!-- Again, but this time as a square thumbnail: -->
{% image_url page.photo "fill-100x100|jpegquality-40" %}
<!-- This time using our custom image serve view: -->
{% image_url page.photo "width-400" "mycustomview_serve" %}
You can pass an optional view name that will be used to serve the image through. The default is ``wagtailimages_serve``
Advanced configuration
======================

View file

@ -1,6 +1,7 @@
from jinja2.ext import Extension
from .shortcuts import get_rendition_or_not_found
from .templatetags.wagtailimages_tags import image_url
def image(image, filterspec, **attrs):
@ -21,6 +22,7 @@ class WagtailImagesExtension(Extension):
self.environment.globals.update({
'image': image,
'image_url': image_url,
})

View file

@ -1,10 +1,14 @@
import re
from django import template
from django.core.exceptions import ImproperlyConfigured
from django.urls import NoReverseMatch
from django.utils.functional import cached_property
from wagtail.images.models import Filter
from wagtail.images.shortcuts import get_rendition_or_not_found
from wagtail.images.views.serve import generate_image_url
register = template.Library()
allowed_filter_pattern = re.compile(r"^[A-Za-z0-9_\-\.]+$")
@ -107,3 +111,14 @@ class ImageNode(template.Node):
for key in self.attrs:
resolved_attrs[key] = self.attrs[key].resolve(context)
return rendition.img_tag(resolved_attrs)
@register.simple_tag()
def image_url(image, filter_spec, viewname='wagtailimages_serve'):
try:
return generate_image_url(image, filter_spec, viewname)
except NoReverseMatch:
raise ImproperlyConfigured(
"'image_url' tag requires the " + viewname + " view to be configured. Please see "
"https://docs.wagtail.io/en/stable/advanced_topics/images/image_serve_view.html#setup for instructions."
)

View file

@ -78,3 +78,15 @@ class TestImagesJinja(TestCase):
self.render('{{ image(myimage, "width-200") }}', {'myimage': self.bad_image}),
'<img alt="missing image" src="/media/not-found" width="0" height="0">'
)
def test_image_url(self):
self.assertRegex(
self.render('{{ image_url(myimage, "width-200") }}', {'myimage': self.image}),
'/images/.*/width-200/{}'.format(self.image.file.name.split('/')[-1]),
)
def test_image_url_custom_view(self):
self.assertRegex(
self.render('{{ image_url(myimage, "width-200", "wagtailimages_serve_custom_view") }}', {'myimage': self.image}),
'/testimages/custom_view/.*/width-200/{}'.format(self.image.file.name.split('/')[-1]),
)

View file

@ -146,6 +146,38 @@ class TestImageTag(TestCase):
context = template.Context({'image_obj': self.image})
temp.render(context)
def render_image_url_tag(self, image, view_name):
temp = template.Template(
'{% load wagtailimages_tags %}{% image_url image_obj "width-400" "' + view_name + '" %}'
)
context = template.Context({'image_obj': image})
return temp.render(context)
def test_image_url(self):
result = self.render_image_url_tag(self.image, 'wagtailimages_serve')
self.assertRegex(
result,
'/images/.*/width-400/{}'.format(self.image.file.name.split('/')[-1]),
)
def test_image_url_custom_view(self):
result = self.render_image_url_tag(self.image, 'wagtailimages_serve_custom_view')
self.assertRegex(
result,
'/testimages/custom_view/.*/width-400/{}'.format(self.image.file.name.split('/')[-1]),
)
def test_image_url_no_imageserve_view_added(self):
# if image_url tag is used, but the image serve view was not defined.
with self.assertRaises(ImproperlyConfigured):
temp = template.Template(
'{% load wagtailimages_tags %}{% image_url image_obj "width-400" "mynonexistingimageserve_view" %}'
)
context = template.Context({'image_obj': self.image})
temp.render(context)
class TestMissingImage(TestCase):
"""

View file

@ -7,6 +7,7 @@ urlpatterns = [
url(r'^actions/serve/(.*)/(\d*)/(.*)/[^/]*', ServeView.as_view(action='serve'), name='wagtailimages_serve_action_serve'),
url(r'^actions/redirect/(.*)/(\d*)/(.*)/[^/]*', ServeView.as_view(action='redirect'), name='wagtailimages_serve_action_redirect'),
url(r'^custom_key/(.*)/(\d*)/(.*)/[^/]*', ServeView.as_view(key='custom'), name='wagtailimages_serve_custom_key'),
url(r'^custom_view/([^/]*)/(\d*)/([^/]*)/[^/]*$', ServeView.as_view(), name='wagtailimages_serve_custom_view'),
url(r'^sendfile/(.*)/(\d*)/(.*)/[^/]*', SendFileView.as_view(), name='wagtailimages_sendfile'),
url(r'^sendfile-dummy/(.*)/(\d*)/(.*)/[^/]*', SendFileView.as_view(backend=dummy_sendfile_backend.sendfile), name='wagtailimages_sendfile_dummy'),
]

View file

@ -8,6 +8,7 @@ from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.http import HttpResponse, HttpResponsePermanentRedirect, StreamingHttpResponse
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils.decorators import classonlymethod
from django.utils.encoding import force_text
from django.views.generic import View
@ -36,6 +37,13 @@ def verify_signature(signature, image_id, filter_spec, key=None):
return force_text(signature) == generate_signature(image_id, filter_spec, key=key)
def generate_image_url(image, filter_spec, viewname='wagtailimages_serve', key=None):
signature = generate_signature(image.id, filter_spec, key)
url = reverse(viewname, args=(signature, image.id, filter_spec))
url += image.file.name[len('original_images/'):]
return url
class ServeView(View):
model = get_image_model()
action = 'serve'