mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-23 14:25:50 +00:00
Add template tag for dynamic image url
Update documentation Co-Authored-By: zerolab <dan@zerolab.org>
This commit is contained in:
parent
ba5138e3fd
commit
515aa61943
7 changed files with 91 additions and 14 deletions
|
|
@ -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
|
||||
======================
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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]),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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'),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
Loading…
Reference in a new issue