【问题标题】: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 %}

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

【问题讨论】:

    标签: django django-templates


    【解决方案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 %}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-07
        • 2022-08-20
        • 2017-02-11
        • 2016-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-08
        相关资源
        最近更新 更多