如果模板丢失,错误消息会更好

Better errors message if template is missing

如果在 django 模板的渲染中缺少模板,我会得到如下所示的异常。

找了很久才找到伪造的部分:

 {% include form.template_name %}

form.template_name 在我的上下文中是空的。

如何在不搜索小时的情况下找到相关模板名称?

我缺少像普通 python 代码那样的回溯。 "Normal" python tracebacks 显示了包含错误的文件和行。

/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

更新

我的个人背景:到目前为止,我避免使用 django 模板,因为有时异常会被默默地忽略,并且像这样的回溯让调试过程感觉就像穿着沉重的混凝土鞋。

我努力摆脱偏见。或者至少找到一种方法如何从模板中获取更好的错误消息。

更新二

我通过 pyCharm 中的单元测试看到了回溯。我没有阅读视图的结果。 "webbrowser" 客户端调用视图。我设置了TEMPLATE_DEBUG=True,但是结果是一样的

正如您似乎使用 PyCharm,您可以使用允许您查看模板上下文的调试器(为此放置断点)documentation

另外,您使用的是哪个版本的 Django?在我的(python3.4 上的 1.8)中,loader.py 文件中没有 find_template()。它可能因此而被删除?

顺便说一句,TemplateDoesNotExist 似乎总是以模板名称作为参数调用,我想是为了能够在错误消息中显示它,但在您的情况下,它是空的。也许这是它难以调试的另一个原因?

之所以看不到通常的 Python 堆栈跟踪,正是因为 Django 模板不是 Python。

它是一种特定的语言,它本身由Python解释,它基于模板构建抽象语法树,然后在渲染阶段评估这棵树。此时,默认情况下无法访问与源相关的信息(例如模板文件)。

Django 中有一个选项可以显示与呈现模板时引发的异常相关的更多相关信息,在 DJango 1.8 之前 TEMPLATE_DEBUG

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

此选项随 Django 1.8 和多个模板引擎的引入而更改,因为调试信息特定于模板引擎的每个实现。

编辑:另见 What is Django's TEMPLATE_DEBUG setting for?

老实说,我一直使用其他发帖人建议的机制来使用实时服务器。但是,由于您正在寻找可能适用于 Jenkins 的解决方案,并且您的堆栈显示您正在经历 debug.py,我查看了那里的调试数据。

我注意到模板引擎应该在异常的 django_template_source 属性中为模板的失败部分添加一段源代码。

在您的例外情况中是否有帮助?如果是这样,您可以捕获异常并在 UT 失败之前打印它。