diff --git a/wagtail/wagtailimages/models.py b/wagtail/wagtailimages/models.py index 8535199e7c..550be20340 100644 --- a/wagtail/wagtailimages/models.py +++ b/wagtail/wagtailimages/models.py @@ -10,7 +10,7 @@ from django.db import models from django.db.models.signals import pre_delete from django.dispatch.dispatcher import receiver from django.utils.safestring import mark_safe -from django.utils.html import escape +from django.utils.html import escape, format_html_join from django.conf import settings from django.utils.translation import ugettext_lazy as _ @@ -242,8 +242,12 @@ class AbstractRendition(models.Model): 'src="%s" width="%d" height="%d" alt="%s"' % (escape(self.url), self.width, self.height, escape(self.image.title)) ) - def img_tag(self): - return mark_safe('' % self.attrs) + def img_tag(self, extra_attributes=None): + if extra_attributes: + extra_attributes_string = format_html_join(' ', '{0}="{1}"', extra_attributes.items()) + return mark_safe('' % (self.attrs, extra_attributes_string)) + else: + return mark_safe('' % self.attrs) class Meta: abstract = True diff --git a/wagtail/wagtailimages/templatetags/image_tags.py b/wagtail/wagtailimages/templatetags/image_tags.py index e59d9cd148..e8a4c2191b 100644 --- a/wagtail/wagtailimages/templatetags/image_tags.py +++ b/wagtail/wagtailimages/templatetags/image_tags.py @@ -7,32 +7,45 @@ register = template.Library() # Local cache of filters, avoid hitting the DB filters = {} + @register.tag(name="image") def image(parser, token): - args = token.split_contents() + bits = token.split_contents()[1:] + image_var = bits[0] + filter_spec = bits[1] + bits = bits[2:] - if len(args) == 3: + if len(bits) == 0: # token is of the form {% image self.photo max-320x200 %} - tag_name, image_var, filter_spec = args return ImageNode(image_var, filter_spec) - elif len(args) == 5: + elif len(bits) == 2: # token is of the form {% image self.photo max-320x200 as img %} - tag_name, image_var, filter_spec, as_token, out_var = args - if as_token != 'as': - raise template.TemplateSyntaxError("'image' tag should be of the form {%% image self.photo max-320x200 %%} or {%% image self.photo max-320x200 as img %%}") + if bits[0] == 'as': + return ImageNode(image_var, filter_spec, output_var_name=bits[1]) - return ImageNode(image_var, filter_spec, out_var) + if len(bits) > 0: + # customized attrs + attrs = {} + for bit in bits: + try: + name,value = bit.split('=') + except: + raise template.TemplateSyntaxError("'image' tag should be of the form {%% image self.photo max-320x200 [ custom-attr=\"value\" [ ... ] ] %%} or {%% image self.photo max-320x200 as img %%}") + attrs[name] = parser.compile_filter(value) # setup to resolve context variables as value - else: - raise template.TemplateSyntaxError("'image' tag should be of the form {%% image self.photo max-320x200 %%} or {%% image self.photo max-320x200 as img %%}") + return ImageNode(image_var, filter_spec, attrs=attrs) + + # something is wrong if we made it this far + raise template.TemplateSyntaxError("'image' tag should be of the form {%% image self.photo max-320x200 [ custom-attr=\"value\" [ ... ] ] %%} or {%% image self.photo max-320x200 as img %%}") class ImageNode(template.Node): - def __init__(self, image_var_name, filter_spec, output_var_name=None): + def __init__(self, image_var_name, filter_spec, output_var_name=None, attrs={}): self.image_var = template.Variable(image_var_name) self.output_var_name = output_var_name + self.attrs = attrs if filter_spec not in filters: filters[filter_spec], _ = Filter.objects.get_or_create(spec=filter_spec) @@ -66,4 +79,7 @@ class ImageNode(template.Node): return '' else: # render the rendition's image tag now - return rendition.img_tag() + resolved_attrs = {} + for key in self.attrs: + resolved_attrs[key] = self.attrs[key].resolve(context) + return rendition.img_tag(resolved_attrs)