【问题标题】:Overwriting a block within an `include`d template from an extended template从扩展模板覆盖 `include`d 模板中的块
【发布时间】:2012-02-20 12:04:56
【问题描述】:

我有以下几点:

base.html

<html>
    {% include 'header.html' %}
    <div>
    {% block content %}Default Content{% endblock %}
    </div>
</html>

header.html

<header>
     {% block logo %}Logo 1{% endblock %}
</header>

homepage.html

{% extend 'base.html' %}
{% block logo %}Logo 2{% endblock %}
{% block content %}Yap Yap Yap{% endblock %}

基本上,这是行不通的。当我渲染 homepage.html 时,我得到:

<html>
    <header>Logo 1</header>
    <div>Yap Yap Yap</div>
</html>

但是如果我将header.html 中的代码移动到base.html(即完全摆脱include),它就可以了。谁能解释为什么会这样?

我感觉这与 included 模板在其父级渲染后渲染有关?

【问题讨论】:

    标签: django django-templates


    【解决方案1】:

    我遇到了类似的问题。我有一个过滤表格模板,其格式为

    {% extends 'base.html' %}
    {% include 'filtered_table.html' %}
    

    filtered_table.html 在哪里:

    {% load render_table from django_tables2 %}
    <div class="panel-body" >
      <form method='GET'>
      <div class="search-form" style="border: 1px solid #000000; background-color:#a3ffaf; overflow: auto;">
    {% block render_form %}
        {% for field in filter.form %}
             {{ field.errors }}
             {{ field.label_tag }} {{ field }}
        {% endfor %}
    {% endblock %}
        <input type='submit' value='Filter' />
        |
        Displaying {{ filter.qs.count }} of {{ filter.queryset.count }} {{ object_name }}s.
        |
        <a href='{{ request.path }}' >Clear</a> <p>
      </div>
    
    {% if table %}
        {% render_table table %}
    {% endif %}
    
    </form>
    
    </div>
    

    我可能想专门手工制作表单,例如像这样拼写每个字段:

    {% block render_form %}
    {{ filter.form.field1.errors }}
    {{ filter.form.field1.label_tag }}
    {{ filter.form.field1 }}
    <p>
    
    {{ filter.form.field2.errors }}
    {{ filter.form.field2.label_tag }}
    {{ filter.form.field2 }} 
    {% endblock %}
    

    不幸的是,因为我不能“扩展”两次,所以我不能得到我的基本布局和自定义过滤表。因此,丑陋(因为将 HTML 结构分成两半)的方法是简单地定义 begin_filtered_table.htmlend_filtered_table.html。然后在定制的情况下,我有两个包含包装定制的情况,对于未定制的情况,filtered_form.html 的定义如下:

    {% include "begin_filtered_table.html" %}
    
        {% for field in filter.form %}
             {{ field.errors }}
             {{ field.label_tag }} {{ field }}
        {% endfor %}
    
    {% include "end_filtered_table.html" %}
    

    这解决了问题,但代价是粗俗。只允许多个扩展会容易得多。

    【讨论】:

      【解决方案2】:

      这是一个已知的限制,我们希望在不久的将来得到解决。

      顺便说一句,假设您有一个更复杂的问题,您已经提到过,另一种解决方法是让 header 成为一个块,而不是用新的自定义包含覆盖这个块。

      base.html

      <html>
          {% block header %}
              {% include 'header.html' %}
          {% endblock %}
          <div>
              {% block content %}Default Content{% endblock %}
          </div>
      </html>
      

      header.html

      <header>
           {% block logo %}Logo 1{% endblock %}
      </header>
      

      homepage.html

      {% extends 'base.html' %}
      
      {% block header %}
          {% include 'homepage_header.html' %}
      {% endblock %}
      
      {% block content %}Yap Yap Yap{% endblock %}
      

      homepage_header.html

      {% extends 'header.html' %}
      
      {% block logo %}Logo 2{% endblock %}
      

      【讨论】:

      • 这行得通,但在我看来它很丑陋。假设您的应用程序中有 30 个不同的页面,每个页面的标题都有一些特殊性(比如徽标或标题),这将创建很多 anypage_header.html 以及每个页面的常规 anypage.html已经有了。这没有意义。
      【解决方案3】:

      您无法覆盖 homepage.html 中的徽标,因为它未在基本模板本身中定义。

      按照您的建议,解决方案是将 header.html 代码移动到 base.html

      【讨论】:

        【解决方案4】:

        from the docs

        include 标签应该被认为是“渲染这个子模板并包含 HTML”的实现,而不是“解析这个子模板并包含它的内容,就好像它是父模板的一部分一样”。这意味着包含的模板之间没有共享状态——每个包含都是一个完全独立的渲染过程。

        因此子模板 (header.html) 被完全渲染并插入到父模板 (base.html) 中,这意味着子模板 (homepage.html) 没有要覆盖的块的概念

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-01-05
          • 2012-04-17
          • 1970-01-01
          • 1970-01-01
          • 2014-05-10
          • 2011-12-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多