Проверьте, существует ли шаблон в шаблоне Django - PullRequest
11 голосов
/ 02 июня 2011

Существует ли готовый способ проверки существования шаблона перед его включением в шаблон Django? Также приветствуются альтернативы, но некоторые из них не будут работать из-за особых обстоятельств.

Например, вот ответ на немного другой вопрос. Это не то, что я ищу: Как проверить, существует ли шаблон в Django?

Ответы [ 4 ]

15 голосов
/ 02 июня 2011

Предполагая, что 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 или нет.

10 голосов
/ 23 сентября 2013

Я столкнулся с этим, пытаясь отобразить шаблон только в том случае, если он существует, и завелся следующим решением тега шаблона:

Включить шаблон, только если он существует

Поместите следующее в 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 шаблона, так что вы можете передавать контекстные переменные так же, как и с простым {% 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.

1 голос
/ 21 января 2015

Мне нужно было условно включить шаблоны, если они существуют, но я хотел использовать переменную для хранения имени шаблона, как вы можете сделать с обычным тегом {% include %}.

Вот мое решение, которое я использовалс Джанго 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)
0 голосов
/ 02 июня 2011

include принимает переменные:

{% include template_name %}

, чтобы вы могли выполнить проверку в своем представлении.

...