Django 模板查找機制: Django 查找模板的過程是在每個 app 的 templates 文件夾中找(而不只是當前 app 中的代碼只在當前的 app 的 templates 文件夾中找)。各個 app 的 templates 形成一個文件夾列表,Django 遍歷這個列表,一個個文件夾進行查找,當在某一個文件夾找到的時候就停止,所有的都遍歷完了還找不到指定的模板的時候就是 Template Not Found (過程類似於Python找包)。這樣設計有利當然也有弊,有利是的地方是一個app可以用另一個app的模板文件,弊是有可能會找錯了。所以我們使用的時候在 templates 中建立一個 app 同名的文件夾,這樣就好了。
這就需要把每個app中的 templates 文件夾中再建一個 app 的名稱,僅和該app相關的模板放在 app/templates/app/ 目錄下面。
例:aptest/templates/aptest,模板調用:return render(request,'aptest/hours_ahead.html',context)
項目aptest下的templates文件夾用於存放所有模板:
base.html,header.html,footer.html放於templates目錄下
current_datetime.html,hours_ahead.html放於templates/aptest目錄下

base.html:定義了一個簡單的 HTML 框架文檔,該站點下所有項目都將使用
<!-- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> --> <!--注釋掉該部分內容,使用header.html中的內容替代 --> {% include 'header.html' %} <!-- include的.html要與其位於同一目錄下 --> <title>{% block title %}{% endblock %}</title> <!-- {% block %} 標簽告訴模板引擎,子模板可以重載這些部分。 每個{% block %}標簽所要做的是告訴模板引擎,該模板下的這一塊內容將有可能被子模板覆蓋。 --> </head> <body> <h1>My helpful timestamp site</h1> {% block content %}{% endblock %} {% block footer %} <!-- 由於子模板並沒有定義 footer 塊,模板系統將使用在父模板中定義的值。 父模板 {% block %} 標簽中的內容總是被當作一條退路。--> <hr> <p>Thanks for visiting my site2.</p> {% endblock %} <!-- {% include 'footer.html' %} --> </body> </html>
header.html內容:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
footer.html內容:(該base.html中未調用)
<hr> <p>Thanks for visiting my siteffffff.</p> </body> </html>
current_datetime.html內容:
{% extends "base.html" %} <!-- 注明擴展base.html --> {% block title %}The current time{% endblock %} <!-- 擴展base中的block title部分 -->
{% block content %} <!-- 擴展base中的block content部分 -->
<p>It is now current_aadate.</p>
{% endblock %}
hours_ahead.html內容:
{% extends "base.html" %} {% block title %}Future time{% endblock %} {% block content %} <p>In {{ hour_offset }} hour(s), it will be next_time .</p> {% endblock %}
最后在view中渲染current_datetime.html,hours_ahead.html,分別顯示如下:


from:http://djangobook.py3k.cn/2.0/chapter04/
可以根據需要使用任意多的繼承次數。 使用繼承的一種常見方式是下面的三層法:
創建 base.html 模板,在其中定義站點的主要外觀感受。 這些都是不常修改甚至從不修改的部分。
為網站的每個區域創建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。這些模板對 base.html 進行拓展,並包含區域特定的風格與設計。1
為每種類型的頁面創建獨立的模板,例如論壇頁面或者圖片庫。 這些模板拓展相應的區域模板。
這個方法可最大限度地重用代碼,並使得向公共區域(如區域級的導航)添加內容成為一件輕松的工作。
以下是使用模板繼承的一些訣竅:
如果在模板中使用 {% extends %} ,必須保證其為模板中的第一個模板標記。 否則,模板繼承將不起作用。3
一般來說,基礎模板中的 {% block %} 標簽越多越好。 記住,子模板不必定義父模板中所有的代碼塊,因此你可以用合理的缺省值對一些代碼塊進行填充,然后只對子模板所需的代碼塊進行(重)定義。 俗話說,鈎子越多越好。4
如果發覺自己在多個模板之間拷貝代碼,你應該考慮將該代碼段放置到父模板的某個 {% block %} 中。
如果你需要訪問父模板中的塊的內容,使用 {{ block.super }}這個標簽吧,這一個魔法變量將會表現出父模板中的內容。 如果只想在上級代碼塊基礎上添加內容,而不是全部重載,該變量就顯得非常有用了。14
不允許在同一個模板中定義多個同名的 {% block %} 。 存在這樣的限制是因為block 標簽的工作方式是雙向的。 也就是說,block 標簽不僅挖了一個要填的坑,也定義了在父模板中這個坑所填充的內容。如果模板中出現了兩個相同名稱的 {% block %} 標簽,父模板將無從得知要使用哪個塊的內容。4
{% extends %} 對所傳入模板名稱使用的加載方法和 get_template() 相同。 也就是說,會將模板名稱被添加到 TEMPLATE_DIRS 設置之后。3
多數情況下, {% extends %} 的參數應該是字符串,但是如果直到運行時方能確定父模板名,這個參數也可以是個變量。 這使得你能夠實現一些很酷的動態功能。
