Django模板:通过扩展模板覆盖包含子模板的块

Chr*_*ele 33 python django django-templates django-inheritance

我想知道是否有人知道如何处理以下古怪的模板结构:

### base.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">

<head>
  <title> {% block title %} Title of the page {% endblock %} </title>
</head>

<body>
  <header>
    {% block header %}
      {% include "base/header.html" %}
    {% endblock header %}
  </header>
  {% block content %}{% endblock %}
</body>

</html>
Run Code Online (Sandbox Code Playgroud)
### base/header.html
<div id="menu-bar">
  {% block nav %}
    {% include "base/nav.html" %}
  {% endblock %}
</div>
Run Code Online (Sandbox Code Playgroud)
### base/nav.html
<nav id="menu">
  <ul>
    <li>
      <a href="/profile/">My Profile</a>
    </li>
    <li>
      <a href="/favs/">My Favorites</a>
    </li>
    {% block extra-content %}{% endblock %}
  </ul>
</nav>
Run Code Online (Sandbox Code Playgroud)

并且,问题的核心:


### app/somepage.html
{% extends "base.html" %}
{% block content %}
  <p>Content is overridden!</p>
{% endblock %}

{% block extra-content %}
  <p>This will not show up, though...</p>
{% endblock %}

{% block nav %}
  <p>Not even this.</p>
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

问题是在扩展模板时,您只能覆盖在父模块中声明的块,而不是它的任何子项.

我想我可以让base.html成为一个空的未使用的嵌套块的外壳,涵盖所有未来的突发事件,但是甚至可以正确覆盖?这是唯一的方法吗?

如果你想知道为什么我有一个围绕base.html的双向包含/扩展工作流,我有很多子模板,我希望在整个项目中使用它们:页眉,页脚,导航,侧边栏等等.整个站点的结构将是一致的,但在许多情况下,站点的整个细分只需要一些子模板.我的想法是在templates/base文件夹下定义子模板,并在其他地方扩展模板/ base-type1.html,templates/base-type2.html等.每种类型只会引用所需的子模板,并覆盖它们以根据需要放置内容.

Ber*_*ant 31

似乎鲜为人知的是,您可以使用with关键字include将变量传递到包含模板的上下文中 - 您可以使用它在包含的模板中指定包含:

# base.html
<html>
    <body>
        {% block header %}{% include "header.html" %}{% endblock %}
    </body>
</html>

# header.html
# some stuff here
<div id="header">
    <img src="logo.png">
    {% include nav_tmpl|default:"navigation.html" %}
</div>

# special_page.html (uses other navigation)
{% extends "base.html" %}
{% block header %}
    {% include "header.html" with nav_tmpl="special_nav.html" %}
    # you might also want to wrap the include in an 'if' tag if you don't want anything
    # included here per default 
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

这种方法至少可以节省一个额外的文件,只是为了覆盖一个块.您还可以使用with关键字通过更大的包含层次结构传递值.


Jul*_*che 12

@Bernhard Vallant 提出解决方案的变体:

# base.html
<html>
    <body>
        {% block header %}{% include "header.html" %}{% endblock %}
    </body>
</html>

# header.html
# some stuff here
<div id="header">
    <img src="logo.png">
    {% include nav_tmpl|default:"navigation.html" %}
</div>

# special_page.html (uses other navigation)
{% extends "base.html" %}
{% block header %}
    {% with nav_tmpl="special_nav.html" %}
        {{ block.super }}
    {% endwith %}
{% endblock %}
Run Code Online (Sandbox Code Playgroud)


Mar*_*cin 6

您可以通过扩展当前包含的模板,然后包括扩展而不是当前包含的基本模板来解决此问题.

  • 如果我只有模板的线性层次结构,您的解决方案将起作用,如上面的基本示例所示。IRL 我的情况是一个分支层次结构,base.html 作为树的树干。如前所述,它还包括页脚、侧边栏等;这意味着我不能简单地翻转包含方向并扩展标题。 (2认同)