Django模版引擎中最強大也是最復(fù)雜的部分就是模版繼承了棘捣。模版繼承可以讓您創(chuàng)建一個基本的“骨架”模版,它包含您站點中的全部元素冰啃,并且可以定義能夠被子模版覆蓋的 blocks 橄镜。
通過從下面這個例子開始括饶,可以容易的理解模版繼承:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>{% block title %}My amazing site{%/span> endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
這個模版,我們把它叫作 base.html恕洲, 它定義了一個可以用于兩列排版頁面的簡單HTML骨架塔橡。“子模版”的工作是用它們的內(nèi)容填充空的blocks霜第。
在這個例子中葛家, block 標(biāo)簽定義了三個可以被子模版內(nèi)容填充的block。 block 告訴模版引擎: 子模版可能會覆蓋掉模版中的這些位置泌类。
子模版可能看起來是這樣的:
{% extends "base.html" %}
{% block title %}My amazing blog{% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
extends 標(biāo)簽是這里的關(guān)鍵癞谒。它告訴模版引擎,這個模版“繼承”了另一個模版。當(dāng)模版系統(tǒng)處理這個模版時弹砚,首先双仍,它將定位父模版——在此例中,就是“base.html”桌吃。
那時殊校,模版引擎將注意到 base.html 中的三個 block 標(biāo)簽,并用子模版中的內(nèi)容來替換這些block读存。根據(jù) blog_entries 的值为流,輸出可能看起來是這樣的:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>My amazing blog</title>
</head>
<body>
<div id="sidebar">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
</div>
<div id="content">
<h2>Entry one</h2>
<p>This is my first entry.</p>
<h2>Entry two</h2>
<p>This is my second entry.</p>
</div>
</body>
</html>
請注意,子模版并沒有定義 sidebar block让簿,所以系統(tǒng)使用了父模版中的值敬察。父模版的 {% block %} 標(biāo)簽中的內(nèi)容總是被用作備選內(nèi)容(fallback)。
這種方式使代碼得到最大程度的復(fù)用尔当,并且使得添加內(nèi)容到共享的內(nèi)容區(qū)域更加簡單莲祸,例如,部分范圍內(nèi)的導(dǎo)航椭迎。
這里是使用繼承的一些提示:
- 如果你在模版中使用 {% extends %} 標(biāo)簽锐帜,它必須是模版中的第一個標(biāo)簽。其他的任何情況下畜号,模版繼承都將無法工作缴阎。
- 在base模版中設(shè)置越多的 {% block %} 標(biāo)簽越好。請記住简软,子模版不必定義全部父模版中的blocks蛮拔,所以,你可以在大多數(shù)blocks中填充合理的默認(rèn)內(nèi)容痹升,然后建炫,只定義你需要的那一個。多一點鉤子總比少一點好疼蛾。
- 如果你發(fā)現(xiàn)你自己在大量的模版中復(fù)制內(nèi)容肛跌,那可能意味著你應(yīng)該把內(nèi)容移動到父模版中的一個 {% block %} 中。
- 如果需要獲取父模板中的block 的內(nèi)容察郁,可以使用{{ block.super }}變量衍慎。如果你想要在父block 中新增內(nèi)容而不是完全覆蓋它,它將非常有用绳锅。使用{{block.super }}插入的數(shù)據(jù)不會被自動轉(zhuǎn)義西饵,因為父模板中的內(nèi)容已經(jīng)被轉(zhuǎn)義。
- 為了更好的可讀性鳞芙,你也可以給你的 {% endblock %} 標(biāo)簽一個 名字 眷柔。
例如:{% block content %}...{% endblock content %}
在大型模版中期虾,這個方法幫你清楚的看到哪一個 {% block %} 標(biāo)簽被關(guān)閉了。
最后驯嘱,請注意您并不能在一個模版中定義多個相同名字的 block 標(biāo)簽镶苞。這個限制的存在是因為block標(biāo)簽的作用是“雙向”的。這個意思是鞠评,block標(biāo)簽不僅提供了一個坑去填茂蚓,它還在 父模版中定義了填坑的內(nèi)容。如果在一個模版中有兩個名字一樣的 block 標(biāo)簽剃幌,模版的父模版將不知道使用哪個block的內(nèi)容聋涨。