http://docs.ckan.org/en/2.9/contributing/frontend/templating.html
template 搜尋順序
以 user/index.html 為例,CKAN 會依以下順序去找:
- 所有載入 extension 的 template 目錄
- 所有載入 extension 的 template_legacy 目錄
- CKAN 的 template 目錄
- CKAN 的 template_legacy 目錄
以上的 legacy 指的是 Genshi template,它們全都被放在 templates_legacy 目錄。若 template 目錄找不到,才會去 legacy 目錄下找。在 CKAN 升級至新版向前相容。
檔案結構
師之前版本一樣,每個 controller 一個目錄、每個 action 一個 template 檔案。
controller 下的 snippets 目錄存放此 controller 專用的 snippet,通用的 snippet 則放在上層目錄。
templates/
base.html # A base template with just core HTML structure
page.html # A base template with default page layout
header.html # The site header.
footer.html # The site footer.
snippets/ # A folder of generic sitewide snippets
home/
index.html # Template for the index action of the home controller
snippets/ # Snippets for the home controller
user/
...
templates_legacy/
# All ckan templates
templating system
Jinja2 使用很多 template 繼承的功能來產生網頁。action 的 template 大多也繼承自 page.html:
{% extends "page.html" %}
其中有許多 block 可讓子 template 覆寫。page.html 決定了基本頁面內容架構,通常只有 {% block primary_content %} 需要自訂。
{% extends "page.html" %}
{% block page_content.html %}
<h1>My page title</h1>
<p>This content will be added to the page</p>
{% endblock %}
慣例/Conventions
Includes
儘量少用 Include。 {% include %} 的內容需放在使用它的程式下的 _snippets_ 目錄。
通常會用 {% snippet %} ,除非 parents context 只能被此 snippet 使用。
Snippets
用 {% snippet %} 比 h.snippet() 好。
snippet 介於 include 和 macro 之間,透過參數決定那些資訊要傳入 snippet。(include 只能接收到 父 context).
儘量 include,因為可讓偵錯變簡單。
Macros
Macros 應節制使用在為通用的 code snippet 建立 custom generator。像是 macros/form.html 中用 macro 來建立表單欄位。
儘量少用,marcro不好擴充及自訂。
extension 中的 template
在 plugin 呼叫 update_config() 向 CKAN 註冊額外的 template 路徑/extra_template_paths。
Custom Control Structures
{% ckan_extends %}
用法和 {% extend %} 很像,但它會向上載入下一個 template。
如果要移除使用者資訊頁面的 breadcrumb。
- 先確定要覆寫的 template:
ckan/templates/user/read.html - 在你的 extension 的 template 目錄下,建立對應要覆寫的目錄及檔案:
ckanext-mytheme/ckanext/mytheme/templates/user/read.html - 在 read.html 中透過 {% ckan_extends %} 拉出 CKAN 核心網頁內容:
{% ckan_extends %} - 然後覆寫原本的 breadcrumb block:
{% ckan_extends %}
{# 以下會移除 breadcrumb #}
{% block breadcrumb %}{% endblock %}
{% ckan_extends %} 會 recursively 執行,{% ckan_extend %} 只會套用在相同名稱的 template。
{% snippet [filepath], [arg1=arg1], [arg2=arg2]... %}
很像 Jinja2 的 {% include %},差別在 CKAN 的 snippet 不會繼承 parent template 的 context,也就是只有明確傳入的參數可用,好處是容易偵錯。用法如下:
{% snippet "package/snippets/package_form.html", data=data, errors=errors %}
{% url_for [arg1=arg1], [arg2=arg2]... %}
用法同 h.url_for():
<a href="{% url_for controller="home", action="index" %}">Home</a>
{% link_for text, [arg1=arg1], [arg2=arg2]... %}
用法同 h.link_for():
<li>{% link_for _("Home"), controller="home", action="index" %}</li>
{% url_for_static path %}
用法同 h.url_for_static():
<script src="{% url_for_static "/javascript/home.js" %}"></script>