在 Django 中捕获 TemplateDoesNotExist

Posted

技术标签:

【中文标题】在 Django 中捕获 TemplateDoesNotExist【英文标题】:Catching TemplateDoesNotExist in Django 【发布时间】:2013-01-23 13:43:32 【问题描述】:

我正在尝试在使用 Django 1.4.3(使用 Python 2.7.2)的项目中使用 SO answer:https://***.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(..)(来自此statement),因此不会传播到我的愚蠢的 API。因此,在渲染过程中,这在我的脸上爆炸了。我将stacktrace上传到pastebin

这是 Django 想要的行为吗?

我最终不再照原样做愚蠢的事情。但我的问题仍然存在。

【问题讨论】:

当你试图捕捉template.loader.TemplateDoesNotExist时会发生什么? 感谢参与。我得到了相同的堆栈 我发布了一个实际上是一种解决方法的答案,我不介意“真实”的解释。 【参考方案1】:

自定义标签呢?这没有提供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" %

【讨论】:

@Marc-OlivierTiteux 我开始做一些快速测试,至少是后备和包含行为以及父模板中的上下文变量可用于包含的模板,它对我有用。让我知道这对你有什么作用。 另请注意,此快速通道不提供默认 include 模板标签的 withonly 参数。您可以通过使用 include 实现作为参考来修改 include_fallback 以轻松完成此操作,但原始问题中似乎不需要附加功能。 谢谢它的工作。实际上,我的用例是:如果模板不存在,什么也不做。在这种情况下,如果我输入 % include_fallback "profile/header.html" "" %,它就不起作用。但它在问题的上下文中效果很好,所以我验证你的答案。不过我会记住这个答案!【参考方案2】:

我找到了我的问题的某种答案,因此我将其发布在这里以供将来参考。

如果我像这样使用我的 template_exists 过滤器

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

如果 profile/header.html 不存在,那么 TemplateDoesNotExist 在页面加载时会奇怪地传播,我会收到服务器错误。但是,如果相反,我在我的模板中使用它:

% 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']) 

在视图中(来自此SO answer)。但是我正在使用一个 CBV,我想保持它相当通用,它是从主模板中调用的。而且我认为如果这个应用程序由于某种原因出现故障,让我的网站正常运行会很好。如果您觉得这很愚蠢,请发表评论(或更好的答案)。

【讨论】:

以上是关于在 Django 中捕获 TemplateDoesNotExist的主要内容,如果未能解决你的问题,请参考以下文章

可以在 Django transaction.atomic() 中捕获并重新引发异常吗?

falsk 与 django 捕获异常

如何在 Django rest 框架中捕获 Model.DoesNotExist 异常?

如何从 Django 中的表单中捕获错误?

如何捕获 Django HTTP 异常?

在Django admin中保存时捕获异常?