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

时间:2010-01-09 23:34:22

标签: django django-templates

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

base.html文件

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

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

延伸-base.html文件

{% block heading %}Super Cool Page!{% endblock %}

但是,对于特殊页面,我不希望页面标题为:

延伸碱基special.html

{% block heading %}{% endblock %}

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

基prefered.html

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

这在模板级别上是否可行,或者我是否需要填写视图?

4 个答案:

答案 0 :(得分:30)

你可以双重包装

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

在没有标题的页面上

{% block noheader %}{% endblock %}

答案 1 :(得分:4)

这样做:

  • base.html - 整体结构<h2>{% block heading %}{% endblock %}</h2>
  • base-without-heading.html - 使用此{% block heading %}{% endblock %}
  • 扩展基础

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

顺便说一下。写下:

{% if heading %}

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

我知道我迟到了,但对于那些(像我一样)仍在寻找解决方案的人来说,这是我的:

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

这是代码:(注意:如果您多次扩展模板,它可能不起作用,但我想您可以通过添加一些递归或其他东西轻松解决此问题。这不是我需要的)< /p>

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)

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

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

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