从扩展模板覆盖`include`d模板中的块

时间:2012-01-27 14:00:24

标签: django django-templates

我有以下内容:

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模板有关?

4 个答案:

答案 0 :(得分:10)

from the docs

  

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

所以子模板(header.html)正在完全呈现并插入到父模板(base.html)中,这意味着没有子模板块的概念(homepage.html)覆盖

答案 1 :(得分:5)

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

顺便说一句,假设你有一个你提到的更复杂的问题,另一个解决方法是使标题成为一个块,而不是用一个新的自定义包覆盖这个块。

<强> 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 %}

答案 2 :(得分:2)

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

{% 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.html end_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" %}

这解决了这个问题,但却以粗暴为代价。允许多次扩展会容易得多。

答案 3 :(得分:0)

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

正如您所建议的那样,解决方案是将 header.html 代码移至 base.html