﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
21077	simple_tag does not allow kwargs with dashes in them	Ilya Semenov		"Consider a simple tag which is supposed to emit HTML code:

{{{#!python
from django.template import Library
from django.utils.html import escape
register = Library()

@register.simple_tag()
def generate_html_tag(element, **kwargs):
	attrs = ''.join(' %s=""%s""' % (k,escape(v)) for k,v in kwargs.items())
	return ""<%s%s/>"" % (element, attrs)
}}}

and this usage:

{{{
{% generate_html_tag ""img"" src=image.url %}
}}}

This works pretty well until we decide to add a data-xxx attribute:

{{{
{% generate_html_tag ""img"" src=image.thumbnail.url data-original-src=image.url %}
}}}

which makes the template engine crash with the exception:
{{{
Traceback:
File ""/venv/lib/python2.7/site-packages/django/core/handlers/base.py"" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File ""/Users/semenov/work/onor/src/onor/views.py"" in index
  4. 	return render(request, 'index.html')
File ""/venv/lib/python2.7/site-packages/django/shortcuts/__init__.py"" in render
  53.     return HttpResponse(loader.render_to_string(*args, **kwargs),
File ""/venv/lib/python2.7/site-packages/django/template/loader.py"" in render_to_string
  170.         t = get_template(template_name)
File ""/venv/lib/python2.7/site-packages/django/template/loader.py"" in get_template
  146.     template, origin = find_template(template_name)
File ""/venv/lib/python2.7/site-packages/django/template/loader.py"" in find_template
  135.             source, display_name = loader(name, dirs)
File ""/venv/lib/python2.7/site-packages/django/template/loader.py"" in __call__
  43.         return self.load_template(template_name, template_dirs)
File ""/venv/lib/python2.7/site-packages/django/template/loader.py"" in load_template
  49.             template = get_template_from_string(source, origin, template_name)
File ""/venv/lib/python2.7/site-packages/django/template/loader.py"" in get_template_from_string
  157.     return Template(source, origin, name)
File ""/venv/lib/python2.7/site-packages/django/template/base.py"" in __init__
  125.         self.nodelist = compile_string(template_string, origin)
File ""/venv/lib/python2.7/site-packages/django/template/base.py"" in compile_string
  153.     return parser.parse()
File ""/venv/lib/python2.7/site-packages/django/template/base.py"" in parse
  274.                     compiled_result = compile_func(self, token)
File ""/venv/lib/python2.7/site-packages/django/template/loader_tags.py"" in do_extends
  215.     nodelist = parser.parse()
File ""/venv/lib/python2.7/site-packages/django/template/base.py"" in parse
  274.                     compiled_result = compile_func(self, token)
File ""/venv/lib/python2.7/site-packages/django/template/loader_tags.py"" in do_block
  190.     nodelist = parser.parse(('endblock',))
File ""/venv/lib/python2.7/site-packages/django/template/base.py"" in parse
  274.                     compiled_result = compile_func(self, token)
File ""/venv/lib/python2.7/site-packages/django/template/base.py"" in generic_tag_compiler
  1015.                               defaults, takes_context, name)
File ""/venv/lib/python2.7/site-packages/django/template/base.py"" in parse_bits
  985.                     ""keyword argument(s)"" % name)

Exception Type: TemplateSyntaxError at /
Exception Value: 'generate_html_tag' received some positional argument(s) after some keyword argument(s)
}}}

This is because `django.template.base.kwarg_re` is quite restrictive and doesn't allow dashes in kwargs names:

{{{#!python
kwarg_re = re.compile(r""(?:(\w+)=)?(.+)"")
}}}

This is a real life use case and we have to apply monkey patches to overcome the problem. Moreover, other projects reuse Django's token_kwargs/parse_bits logic and then fail in the same way: https://github.com/matthewwithanm/django-imagekit/pull/253

Obviously, this is easily fixable by adjusting the regular expression:
{{{#!python
kwarg_re = re.compile(r""(?:([\w+-])=)?(.+)"")
}}}

I'm not sure if the tag arguments syntax was restricted this way on purpose or not. You see, it would at least make sense if it repeated Python's own syntax for keyword arguments (something like `[a-z_]\w+`), but currently as it's simply `\w+` it allows keyword arguments like `2=2` (but doesn't allow `foo-bar=1`) so in my opinion it's overly restrictive in one sense and insufficiently restrictive in other sense."	Bug	closed	Template system	1.5	Normal	wontfix		k@…	Accepted	0	0	0	0	0	0
