捕获Django中的TemplateDoesNotExist
我正在尝试在一个使用 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" %}