捕获Django中的TemplateDoesNotExist

6 投票
2 回答
1909 浏览
提问于 2025-04-17 13:24

我正在尝试在一个使用 Django 1.4.3(搭配 Python 2.7.2)的项目中使用 StackOverflow 上提到的模板标签:https://stackoverflow.com/a/6217194/493211

我把它改成了这样:

from django import template


register = template.Library()

@register.filter
def template_exists(template_name):
    try:
        template.loader.get_template(template_name)
        return True
    except template.TemplateDoesNotExist:
        return False

这样我就可以在另一个模板中像这样使用它:

{% if 'profile/header.html'|template_exists %}        
  {% include 'profile/header.html' %}
{% else %}
  {% include 'common/header.html' %}
{% endif %}

这样,我就可以避免像改变我的应用在 INSTALLED_APPS 中的顺序这样的解决方案。

但是,它并没有工作。如果模板不存在,那么在堆栈/控制台中会抛出异常,但这个异常并没有传递到 get_template(..)(来自这个语句),因此也没有传递到我的愚蠢 API。这导致在渲染时出现了问题。我把堆栈跟踪上传到了pastebin

这是 Django 的预期行为吗?

我最终停止了这样的愚蠢做法。但我的问题依然存在。

2 个回答

1

我找到了一些关于我问题的答案,所以我把它放在这里,方便以后参考。

如果我像这样使用我的模板存在性过滤器

{% if 'profile/header.html'|template_exists %}        
  {% include 'profile/header.html' %}
{% else %}
  {% include 'common/header.html' %}
{% endif %}

而且如果 profile/header.html 文件不存在,那么在页面加载时会奇怪地出现一个“模板不存在”的错误,导致服务器出错。不过,如果我在我的模板中使用这个:

{% with 'profile/header.html' as var_templ %}
  {% if var_templ|template_exists %}
    {% include var_templ %}
  {% else %}
    {% include 'common/header.html' %}
  {% endif %}
{% endwith %}

那么,一切就正常运作了!

显然,我本可以在视图中使用

django.template.loader.select_template(['profile/header.html','common/header.html']) 

(来自这个 StackOverflow的回答)。但是我使用的是一个类视图(CBV),我想保持它的通用性,而这个是从主模板调用的。而且我觉得如果这个应用因为某种原因出现问题,我的网站还能正常工作,那就太好了。如果你觉得这很傻,请留言(或者给个更好的答案)。

2

那自定义标签怎么样呢?虽然这不能完全替代include的所有功能,但看起来可以满足问题中的需求。

@register.simple_tag(takes_context=True)
def include_fallback(context, *template_choices):
    t = django.template.loader.select_template(template_choices)
    return t.render(context)

然后在你的模板里:

{% include_fallback "profile/header.html" "common/header.html" %}

撰写回答