#25423 closed Cleanup/optimization (fixed)
Using custom tag without {% load %} result in confusing traceback
Reported by: | Yuchen Ying | Owned by: | |
---|---|---|---|
Component: | Template system | Version: | 1.8 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
In the following sample code, the author clearly registered the new tag but forgot to load it in template.
from django import template from django import test from django.template import context register = template.Library() @register.simple_tag(name="test") def simple_tag(*args): return "nothing here" class MyTest(test.TestCase): def test_forgot_to_load(self): TEMPLATE = """ {% if True %} {% test %} {% endif %} """ template.Template(TEMPLATE).render(context.Context())
This code will create the following traceback in Python 3:
Traceback (most recent call last): File "/home/ych/.py3kvenv/lib/python3.4/site-packages/django/template/base.py", line 337, in parse compile_func = self.tags[command] KeyError: 'test' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/ych/testproject/testproject/test.py", line 25, in test_forgot_to_load template.Template(TEMPLATE).render(context.Context()) File "/home/ych/.py3kvenv/lib/python3.4/site-packages/django/template/base.py", line 190, in __init__ self.nodelist = engine.compile_string(template_string, origin) File "/home/ych/.py3kvenv/lib/python3.4/site-packages/django/template/engine.py", line 261, in compile_string return parser.parse() File "/home/ych/.py3kvenv/lib/python3.4/site-packages/django/template/base.py", line 341, in parse compiled_result = compile_func(self, token) File "/home/ych/.py3kvenv/lib/python3.4/site-packages/django/template/defaulttags.py", line 1014, in do_if nodelist = parser.parse(('elif', 'else', 'endif')) File "/home/ych/.py3kvenv/lib/python3.4/site-packages/django/template/base.py", line 339, in parse self.invalid_block_tag(token, command, parse_until) File "/home/ych/.py3kvenv/lib/python3.4/site-packages/django/template/base.py", line 394, in invalid_block_tag (command, get_text_list(["'%s'" % p for p in parse_until]))) django.template.base.TemplateSyntaxError: Invalid block tag: 'test', expected 'elif', 'else' or 'endif'
And this is the traceback in Python2:
Traceback (most recent call last): File "/home/ych/testproject/testproject/test.py", line 25, in test_forgot_to_load template.Template(TEMPLATE).render(context.Context()) File "/home/ych/.py2kvenv/local/lib/python2.7/site-packages/django/template/base.py", line 190, in __init__ self.nodelist = engine.compile_string(template_string, origin) File "/home/ych/.py2kvenv/local/lib/python2.7/site-packages/django/template/engine.py", line 261, in compile_string return parser.parse() File "/home/ych/.py2kvenv/local/lib/python2.7/site-packages/django/template/base.py", line 341, in parse compiled_result = compile_func(self, token) File "/home/ych/.py2kvenv/local/lib/python2.7/site-packages/django/template/defaulttags.py", line 1014, in do_if nodelist = parser.parse(('elif', 'else', 'endif')) File "/home/ych/.py2kvenv/local/lib/python2.7/site-packages/django/template/base.py", line 339, in parse self.invalid_block_tag(token, command, parse_until) File "/home/ych/.py2kvenv/local/lib/python2.7/site-packages/django/template/base.py", line 394, in invalid_block_tag (command, get_text_list(["'%s'" % p for p in parse_until]))) TemplateSyntaxError: Invalid block tag: 'test', expected 'elif', 'else' or 'endif'
It says invalid block tag, but invalid how? Does that mean I should not use it at the specified location (which was my understanding when encountered this traceback), or invalid in other ways (this is the case here)? If invalid in other ways, how should I fix it?
The traceback is slightly better in Python3 in that it let you know it's looking for 'test' in a dict but cannot find it, which will help you debugging this issue. But in both case it's unclear that this can be fixed with a simple {% load %} tag.
Without knowing the implementation detail, I find it confusing that after registering the tag I still need to load it in template. If this extra step is unavoidable, could you please improve the error message a little bit? Something like:
Encountered unknown tag %s when parsing template %s at line %d: expect %s. Did you forgot to register or load this tag?
Change History (7)
comment:1 by , 9 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 9 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:3 by , 9 years ago
Has patch: | set |
---|
comment:4 by , 9 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:5 by , 9 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
I did some experimentation with this and it looks like it's not possible to distinguish between a truly unknown template tag and a template tag that isn't registered as a starting tag but might be an ending tag (like
elif
,endif
, etc). That's why the error message lists some "expected" tags.However I do have personal experience with Django users who have been very confused by this message and didn't even think to check if they had loaded the tag. I think your "Did you forgot to register or load this tag?" message is a good solution. I've created a patch and PR to add that to the error message: https://github.com/django/django/pull/5392