Лучшее сообщение об ошибках, если шаблон отсутствует

Если шаблон отсутствует внутри рендеринга шаблона django, я получаю исключение, как показано ниже.

После долгого поиска я нашел фиктивную часть:

 {% include form.template_name %}

form.template_name в моем контексте было пустым.

Как найти подходящее имя шаблона без поиска часов?

Мне не хватает трассировки, как для обычного кода на Python. "Нормальные" трассировки python показывают мне файл и строку, содержащие ошибку.

/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, так как иногда исключения бесшумно игнорируются, и подобные трассировки делают процесс отладки похожим на тяжелую обувь из бетона.

Я пытаюсь избавиться от своих предрассудков. Или наименее найти способ получения сообщений об ошибках из шаблонов.

Обновление II

Я вижу трассировку через unittest внутри pyCharm. Я не читаю результат обзора. Клиент "webbrowser" вызывает представление. Я установил TEMPLATE_DEBUG = True, но результат тот же.

Ответ 1

Честно говоря, я всегда использовал механизмы, предлагаемые другими плакатами с живым сервером. Однако, поскольку вы ищете решение, которое может работать в Jenkins, и ваш стек показывает, что вы проходите через debug.py, я просмотрел там отладочные данные.

Я заметил, что движок шаблона должен добавить фрагмент исходного кода для поврежденной части шаблона в атрибуте django_template_source в Exception.

Является ли это в вашем исключении и полезным? Если это так, вы можете поймать исключение и распечатать его перед сбоем UT.

Ответ 2

Причина, по которой вы не видите обычную стеклу Python, это именно то, что шаблоны Django не являются Python.

Это конкретный язык, который сам интерпретируется Python, который строит абстрактное синтаксическое дерево на основе шаблона и затем оценивает это дерево во время фазы рендеринга. На данный момент информация, связанная с источником (например, файл шаблона), по умолчанию недоступна.

В Django есть опция для отображения более релевантной информации, связанной с исключением, созданным при рендеринге шаблона, TEMPLATE_DEBUG перед DJango 1.8.

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

Эта опция была изменена с помощью Django 1.8 и внедрением нескольких механизмов шаблонов, поскольку информация об отладке относится к каждой реализации механизма шаблонов.

Изменить: см. также Что такое параметр TEMPLATE_DEBUG для Django для?

Ответ 3

Как вы, кажется, используете PyCharm, вы можете использовать отладчик, который позволяет вам просматривать контекст ваших шаблонов (разместить точки останова для этого) documentation

Также, какую версию Django вы используете? В моем (1.8 на python3.4) в файле loader.py нет find_template(). Возможно, это было удалено по этой причине?

Btw, TemplateDoesNotExist, кажется, всегда вызывается с именем шаблона в качестве параметра, я думаю, что он не смог отобразить его в сообщении об ошибке, но в вашем случае он пуст. Может быть, это еще одна причина для его отладки?