检查Django模板中是否存在模板

时间:2011-06-02 15:35:54

标签: django templates try-catch exists

在将模板包含在Django模板中之前,是否存在检查模板是否存在的开箱即用方法?也欢迎替代方案,但由于特殊情况,其中一些方法不起作用。

例如,这是一个略有不同的问题的答案。这不是我想要的: How to check if a template exists in Django?

4 个答案:

答案 0 :(得分:15)

假设include如果你传递了一个错误的模板引用,它就不会爆炸,这可能是最好的方法。您的另一种选择是创建一个模板标签,它基本上对您提到的链接进行检查。

非常基本的实施:

from django import template

register = template.Library()

@register.simple_tag
def template_exists(template_name):
    try:
        django.template.loader.get_template(template_name)
        return "Template exists"
    except template.TemplateDoesNotExist:
        return "Template doesn't exist"

在你的模板中:

{% template_exists 'someapp/sometemplate.html' %}

那个标签实际上并不是那么有用,所以你可能想要创建一个实际上向上下文添加变量的标签,然后你可以在if语句中检查或不检查。

答案 1 :(得分:10)

我遇到过这种情况,只有当模板存在时才会显示模板,并使用以下模板标记解决方案:

仅在模板存在时包含模板

将以下内容放入yourapp/templatetags/include_maybe.py

from django import template
from django.template.loader_tags import do_include
from django.template.defaulttags import CommentNode
register = template.Library()

@register.tag('include_maybe')
def do_include_maybe(parser, token):
    "Source: http://stackoverflow.com/a/18951166/15690"
    bits = token.split_contents()
    if len(bits) < 2:
        raise template.TemplateSyntaxError(
            "%r tag takes at least one argument: "
            "the name of the template to be included." % bits[0])

    try:
        silent_node = do_include(parser, token)
    except template.TemplateDoesNotExist:
        # Django < 1.7
        return CommentNode()

    _orig_render = silent_node.render
    def wrapped_render(*args, **kwargs):
        try:
            return _orig_render(*args, **kwargs)
        except template.TemplateDoesNotExist:
            return CommentNode()
    silent_node.render = wrapped_render
    return silent_node

通过在模板顶部添加{% load include_maybe %}并在代码中使用{% include_maybe "my_template_name.html" %},从模板中访问它。

这种方法具有捎带现有模板包含标记的良好副作用,因此您可以使用与普通{% include %}相同的方式传递上下文变量。

根据模板是否存在进行切换

但是,如果模板存在,我想在嵌入网站上添加一些额外的格式。我写了一个过滤器,让您可以使用现有的{% if_template_exists %}标记,而不是编写{% if %}标记。

为此,请将以下内容放入yourapp/templatetags/include_maybe.py(或其他内容)

from django import template
from django.template.defaultfilters import stringfilter


register = template.Library()

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

然后,从您的模板中,您可以执行以下操作:

{% load include_maybe %}

{% if "my_template_name"|template_exists %}
     <div>
         <h1>Notice!</h1>
         <div class="included">
             {% include_maybe "my_template_name" %}
         </div>
     </div>
{% endif %}

使用自定义过滤器而不是使用自定义标记的优点是您可以执行以下操作:

{% if "my_template_name"|template_exists and user.is_authenticated %}...{% endif %}

而不是使用多个{% if %}代码。

请注意,您仍然必须使用include_maybe

答案 2 :(得分:1)

我需要有条件地包含模板(如果它们存在)但我想使用变量存储模板名称,就像使用常规{% include %}标记一样。

这是我与Django 1.7一起使用的解决方案:

from django import template
from django.template.loader_tags import do_include

register = template.Library()


class TryIncludeNode(template.Node):
    """
    A Node that instantiates an IncludeNode but wraps its render() in a
    try/except in case the template doesn't exist.
    """
    def __init__(self, parser, token):
        self.include_node = do_include(parser, token)

    def render(self, context):
        try:
            return self.include_node.render(context)
        except template.TemplateDoesNotExist:
            return ''


@register.tag('try_include')
def try_include(parser, token):
    """
    Include the specified template but only if it exists.
    """
    return TryIncludeNode(parser, token)

答案 3 :(得分:0)

include接受变量:

{% include template_name %}

所以你可以在你的视图中进行检查。