2012-04-03 105 views
25

我想知道如果任何人知道如何处理以下古怪的模板结构:Django模板:包括儿童的首要块模板通过扩展模板

### 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> 

### base/header.html 
<div id="menu-bar"> 
    {% block nav %} 
    {% include "base/nav.html" %} 
    {% endblock %} 
</div> 

### 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> 

而且,问题的核心:


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

问题是扩展模板时,您只能覆盖在父代中声明的区块,而不是其任何子代。

我想我可以使base.html成为空的未使用的嵌套块,以覆盖所有未来的意外情况,但甚至会覆盖正确?那是唯一的方法吗?

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

+1

嘛,张贴后,我见[这个问题](http://stackoverflow.com/questions/9034331/overwriting-a-block-within-an-即使在彻底搜索堆栈溢出和谷歌搜索之后,也会在侧边栏中弹出包含模板从扩展模板。我理解django中这个限制的机制,但是男人,其影响令人沮丧。 – 2012-04-03 15:32:43

+0

完全试图发布此作为答案,但我的新的堆栈帐户缺乏代表...忘了这一点。 – 2012-04-03 15:33:14

+0

对于未来的发现者:[前述问题](http://stackoverflow.com/questions/9034331/overwriting-a-block-within-an-included-template-from-an-extended-template)有一个基本的代码示例下面的几个答案证明了@ Marcin的有益策略。 – 2012-04-03 16:11:40

回答

5

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

+0

如果我只有线性层次结构的模板,那么您的解决方案就可以工作,就像上面的裸机示例一样。 IRL我的情况是以base.html作为树干的分支层次结构。正如简要提到的那样,它还包括页脚,侧边栏等;这意味着我不能简单地翻转包含的方向并扩展标题。 – 2012-04-03 15:40:55

+0

@ChrisKeele只要你的包含在一个块中,你可以用包含派生模板来替换包含,所以是的,这是行得通的。 – Marcin 2012-04-03 15:45:54

+0

因此,如果我有一个header.html和一个footer.html,我会使每个扩展base.html,然后在example.html ...做什么?包括页眉和页脚?并在此基础上扩展基础?对不起,需要进一步澄清,但我现在远离代码,并且“用包含派生模板替换包含”对我来说很难想象没有沙箱。 :) – 2012-04-03 15:51:33

23

这似乎是鲜为人知的,你可以使用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 %} 

这种方法至少可以避免为了覆盖块而增加一个文件。您也可以使用with关键字将值传递给包含更大的包含层次结构。

9

一个更简洁的变体的solution proposed by @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 %}