测试模板中是不是存在模板块

Posted

技术标签:

【中文标题】测试模板中是不是存在模板块【英文标题】:Test for existence of template block in a template测试模板中是否存在模板块 【发布时间】:2011-01-03 08:54:31 【问题描述】:

我有一个结构,在我的基本模板中,(% block heading % 通常有一个页面标题:

base.html

<h2>% block heading %% endblock %</h2>

大多数时候,我会通过扩展 base 的模板传递这样的标题:

extends-base.html

% block heading %Super Cool Page!% endblock %

但是,对于一个特殊的页面,我不想有一个页面标题:

extends-base-special.html

% block heading %% endblock %

理想情况下,这应该排除&lt;h2&gt; 标签。现在,我可以让所有扩展模板都包含&lt;h2&gt; 标签,但这违反了 DRY,因为每个页面都应该具有相同的页面级标题元素。我更喜欢这样做(这似乎不起作用):

base-prefered.html

% if heading %
<h2>% block heading %% endblock %</h2>
% endif %

这在模板级别上是否可行,还是我必须为此投入视图?

【问题讨论】:

【参考方案1】:

你可以把它包起来

% block noheader %
  <h2>% block header %Super Cool Page!% endblock header %</h2>
% endblock noheader %

在没有标题的页面上

% block noheader %% endblock %

【讨论】:

是的,这就是我们最终的结果。尽管如此,通过后代模板测试块集的存在还是很有用的。 Ew。 +1,因为它解决了问题 - 但对于每个需要这个的模板来说,记住这一点很痛苦。 这是正确的解决方案,但 % block noheader % 是一个坏名字,它使解决方案看起来比实际更hacker。更好的命名是% block header % 用于外部块,% block header-text % 用于内部块。然后名称更准确地反映了您希望能够在后代模板中覆盖的部分。 这是说在Django中这个问题没有合适的解决方案 这行得通,但是... bleh。 Rails 通过content_for? 很好地解决了这个问题【参考方案2】:

这样做:

base.html - 整个结构&lt;h2&gt;% block heading %% endblock %&lt;/h2&gt; base-without-heading.html - 使用 % block heading %% endblock % 扩展基础

然后扩展第一个或第二个模板。我相信这应该是最简单的方法。

顺便说一句。通过写作:

% if heading %

您实际上是在要求名称为“标题”的上下文中元素的布尔值。 django 标记语言的元素不在上下文中,所以你不能要求它们。你可以写一个标签,在上下文中添加一些东西,我曾经需要这样的东西并使用它,但我不相信这是要走的路。以上解决方案应该工作(我没有机器来检查这个),这是 IMNSHO 的最佳方式。

【讨论】:

【参考方案3】:

Afaik 目前还没有真正好的和简单的解决方案。除了 czarchaic 提供的选项之外,您还可以编写自己的模板标签,如 Jarret Hardie's answer 到 "How to test for use of a django template block?" 中所述。但是,恕我直言,最好和最优雅的方式是 % capture as ... % 模板标签 - 不幸的是它还没有实现:https://code.djangoproject.com/ticket/6378

【讨论】:

是的。这一直是我对 Django 的唯一主要批评。【参考方案4】:

我知道我迟到了,但对于任何(像我一样)仍在寻找解决该问题的人,这里是我的:

我创建了一个自定义 TemplateBackend,它将给定模板中每个块的名称放在一个名为“FILLED_BLOCKS”的上下文变量中。

这是代码:(注意:如果您多次扩展模板,它可能无法正常工作,但我想您可以通过添加一点递归或其他东西轻松解决这个问题。这不是我需要的)

from django.template.backends.django import DjangoTemplates, Template, reraise, TemplateDoesNotExist
from django.template.context import make_context
from django.template.engine import Engine
from django.template.loader_tags import ExtendsNode

class CustomBackend(DjangoTemplates):
    def from_string(self, template_code):
        return CustomTemplate(self.engine.from_string(template_code))

    def get_template(self, template_name):
        try:
            return CustomTemplate(self.engine.get_template(template_name), self)
        except TemplateDoesNotExist as exc:
            reraise(exc, self)


class CustomTemplate(Template):
    def get_filled_blocks(self):
        nodes = self.template.nodelist.get_nodes_by_type(ExtendsNode)
        if len(nodes) == 0:
            return []
        blocks = []
        for node in nodes:
            for block in node.blocks.values():
                if len(block.nodelist) != 0:
                    blocks.append(block.name)
        return blocks
    
    def render(self, context=None, request=None):
            context['FILLED_BLOCKS'] = self.get_filled_blocks()
            context = make_context(context, request, autoescape=self.backend.engine.autoescape)
            try:
                return self.template.render(context)
            except TemplateDoesNotExist as exc:
                reraise(exc, self.backend)

只需将此文件的路径放入您的 settings.py 中的 TEMPLATES['BACKEND']

像这样在你的模板中使用它:

% if 'heading' in FILLED_BLOCKS %
   <h2>% block heading %% endblock %</h2>
% endif %

【讨论】:

以上是关于测试模板中是不是存在模板块的主要内容,如果未能解决你的问题,请参考以下文章

如何在页面呈现期间测试是不是存在 JSF 导航案例

Spring junit 测试模板可能不存在

渲染前检查模板是不是存在

Rspec - 如何测试邮件是不是使用正确的模板

NUnit 是不是有 Visual Studio 测试项目模板?

Python Django 模板和测试变量是不是为空或空字符串