Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better errors message if template is missing

If a template is missing deep inside the rendering of a django template, I get a exception like below.

After searching very long I found the bogus part:

 {% include form.template_name %}

form.template_name was empty in my context.

How can I find the relevant template name without searching for hours?

I am missing a traceback like for normal python code. "Normal" python tracebacks show me the file and line which contain the bug.

/home/foo_fm_d/bin/python /usr/local/pycharm-community-4.5/helpers/pycharm/utrunner.py /home/foo_fm_d/src/foo-time/foo_time/tests/unit/views/user/test_preview_of_next_days.py::EditTestCase::test_preview_of_next_days true
Testing started at 09:26 ...

Error
Traceback (most recent call last):
  File "/home/foo_fm_d/src/foo-time/foo_time/tests/unit/views/user/test_preview_of_next_days.py", line 11, in test_preview_of_next_days
    self.admin_client.get(url)
  File "/home/foo_fm_d/src/djangotools/djangotools/utils/testutils.py", line 275, in get
    response = super(Client, self).get(path, data, **extra)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/test/client.py", line 473, in get
    response = super(Client, self).get(path, data=data, **extra)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/test/client.py", line 280, in get
    return self.request(**r)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/test/client.py", line 444, in request
    six.reraise(*exc_info)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 137, in get_response
    response = response.render()
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/response.py", line 82, in rendered_content
    content = template.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 140, in render
    return self._render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
    return self.nodelist.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/debug.py", line 78, in render_node
    return node.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 123, in render
    return compiled_parent._render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
    return self.nodelist.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/debug.py", line 78, in render_node
    return node.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 123, in render
    return compiled_parent._render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
    return self.nodelist.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/debug.py", line 78, in render_node
    return node.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/debug.py", line 78, in render_node
    return node.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/debug.py", line 88, in render
    output = self.filter_expression.resolve(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 585, in resolve
    obj = self.var.resolve(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 735, in resolve
    value = self._resolve_lookup(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 789, in _resolve_lookup
    current = current()
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 72, in super
    return mark_safe(self.render(self.context))
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/debug.py", line 78, in render_node
    return node.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/debug.py", line 78, in render_node
    return node.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/debug.py", line 78, in render_node
    return node.render(context)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 166, in render
    template = get_template(template_name)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader.py", line 138, in get_template
    template, origin = find_template(template_name)
  File "/home/foo_fm_d/local/lib/python2.7/site-packages/django/template/loader.py", line 131, in find_template
    raise TemplateDoesNotExist(name)
TemplateDoesNotExist


Process finished with exit code 0

Update

My personal background: Up to now I avoid django templates since sometimes exceptions get silently ignored and tracebacks like this make the debugging process feel like wearing heavy shoes made of concrete.

I try to get get rid of my prejudices. Or least find a way how to get better error messages from templates.

Update II

I see the traceback via a unittest inside pyCharm. I don't read the result of the view. The "webbrowser" Client calls the view. I set TEMPLATE_DEBUG=True, but the result is the same.

like image 375
guettli Avatar asked May 26 '15 07:05

guettli


2 Answers

The reason why you don't see the usual Python stacktrace is precisely that Django templates are not Python.

It is a specific language which is itself interpreted by Python, which builds an abstract syntax tree based on the template and then evaluates this tree during the rendering phase. At this point, information associated with the source (e.g. the template file) is not accessible by default.

There is an option within Django to show more relevant information associated with exception raised while rendering the template, it is TEMPLATE_DEBUG before DJango 1.8.

See https://docs.djangoproject.com/en/1.8/ref/settings/#template-debug

This option changed with Django 1.8 and the introduction of multiple template engines as debugging information are specific to each implementation of template engine.

Edit: See also What is Django's TEMPLATE_DEBUG setting for?

like image 154
Weier Avatar answered Oct 18 '22 19:10

Weier


To be honest, I've always used the mechanisms the other posters suggested with a live server. However, since you are looking for a solution that might work in Jenkins and your stack shows you are going through debug.py, I had a look at the debug data there.

I notice that the template engine should add a snippet of source code for the failing part of the template in the django_template_source attribute on the Exception.

Is that present in your exception and helpful? If so, you could catch the exception and print it before failing your UT.

like image 2
Peter Brittain Avatar answered Oct 18 '22 20:10

Peter Brittain