Mako 模板
Mako 是Python語言的一個模板處理庫.
它能提供編譯為常見的非XML語法的高性能的Python模塊.
Mako 的語法及API融合了很多模塊系統的亮點, 如常用的 Django, Cheetah, Myghty, Genshi等等.
從概念上講, Mako 屬於一種內嵌Python語言(如Python的服務端頁面). 這樣模板開發者精確的想法布局實現及簡單而直接地繼承. 模式靈活同時還保證了與應用與Python的調用及語義的緊密聯系.
<%inherit file="base.html"/>
<%
rows = [[v for v in range(0,10)] for row in range(0,10)]
%>
<table>
% for row in rows:
${makerow(row)}
% endfor
</table>
<%def name="makerow(row)">
<tr>
% for name in row:
<td>${name}</td>
% endfor
</tr>
</%def>
功能
API簡潔, 最簡單的例子, 只需要引用一個 Template class 即可.
from mako.template import Template
print Template("hello ${data}!").render(data="world")
另一個例子,使用文件模板以及模板緩存,模板文件優先查詢的處理.
Insanely Fast. An included bench suite, adapted from a suite included with Genshi, has these results for a simple three-sectioned layout:
Mako: 1.10 ms Kid: 14.54 ms
- 標准模板功能
- 模板結構,邏輯控制使用標准Python語法(如 循環語句, 條件語句等)
- straight Python blocks, inline or at the module-level
- 可重復使用模板塊
- can access variables from their enclosing scope as well as the template’s request context
- 模塊任意嵌套
- can specify regular Python argument signatures
- outer-level callable blocks can be called by other templates or controller code (i.e. “method call”)
- calls to functions can define any number of sub-blocks of content which are accessible to the called function (i.e. “component-call-with-content”). This is the basis for nestable custom tags.
- 模板繼承
- supports “multi-zoned” inheritance - define any number of areas in the base template to be overridden.
- supports “chaining” style inheritance - call next.body() to call the “inner” content.
- the full inheritance hierarchy is navigable in both directions (i.e. parent and child) from anywhere in the chain.
- inheritance is dynamic ! Specify a function instead of a filename to calculate inheritance on the fly for every request.
例子
- 基本用法
from mako.template import Template
mytemplate = Template("hello world!")
print mytemplate.render()
傳給 Template 的模板文本被處理成一種類似 Python 模塊的對象.
這個模塊對象有一個 render_body() 方法, 用於將模板處理為最終的輸出結果.
當 mytemplate.render() 時,Mako 會處理當前的運行環境並調用 render_body() 方法渲染模板后返回處理結果為一個 字符串.
The code inside the render_body() function has access to a namespace of variables. You can specify these variables by sending them as additional keyword arguments to the render() method:
from mako.template import Template
mytemplate = Template("hello, ${name}!")
print mytemplate.render(name="openerp")
- 基於文件的模板
使用文件做為模板代碼源, 只需要使用 filename 參數指定文件路徑即可:
from mako.template import Template
mytemplate = Template(filename='/test.html')
print mytemplate.render()
- 使用 TemplateLookup 匹配最佳模板
到目前, 所有的例子還都是只使用單一的 Template 模板.
如果模板代碼中引用一個本地的另一個模板資源, Mako 則可以使用簡單的 URI 串來指定查找位置.
因此, TemplateLookup 類就解決了在一個模板中引用其它模板的問題.
該類將按給定的目錄列表查找模板, This class is constructed given a list of directories in which to search for templates, as well as keyword arguments that will be passed to the Template objects it creates:
from mako.template import Template
from mako.lookup import TemplateLookup
mylookup = TemplateLookup(directories=[''])
mytemplate = Tempalte('<% include file="header.txt"/> Hello!',lookup=mylookup)
上面的代碼, 則創建了一個引用了 “header.txt” 文件的模板.
為了讓系統能找到 “header.txt” 模板, 我們傳了一個 TemplateLookup 對象過去,告訴系統從當前文件夾中查找 “header.txt”.
語法
- 表達式
模板最簡單的表達式就是模板變量的替換了.
${} 的語法類似於 Perl, Genshi, JSP EL等模板系統的語法:
${x}
${5%5}
${7*2}
${pow(x,2) + pow(y,2)}
- 流程控制
- 條件語句(如: if/else)
- 循環語句(如: for 與 while)
- 異常控制(如: try/except)
模板的流程控制完全使用 Python 語言的流程控制語法, 只不過, 在模板流程控制結束, 需要使用 “%end<name>”來做為控制結束符. 其中 “<name>” 為控制語句的 Python 保留字. 例如:
% if user_name == 'openerp':
valid user
% endif
% if a > 1:
a is positive number
% elif a == 0:
a is 0
% else:
a is negative number
% endif
<table>
% for a in [1,2,3,4,5]:
<tr>
<td>
${a}
</td>
</tr>
% endfor
</table>
- Python 代碼塊
你可以在模板的 <% %> 標符內隨意使用 Python 代碼:
<%
a = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
b = a.values()
%>
% for x in b:
${x}
% endfor
- Module-level Blocks
<% %> Python 代碼塊的另一種方式是可以使用 <%! %> 做為定界符.
模板里這個標簽內的代碼可以執行, 但是函數定義里的代碼並不立即執行.
<%!
import cherrypy
def get_user_from_session():
return cherrypy.session['current_user']
%>
Therefore, this code does not have access to the template’s context and is only executed when the template is loaded into memory (which can be only once per application, or more, depending on the runtime environment).
- Mako Tags
<%page>
<%page> 標簽是在模板中常用的標簽, 在標簽內可以配置頁面的緩存參數,以及模板引用時需要的一些可選擇的列表.
Also defines caching characteristics.
<%page args="x, y, z='default'"/>
<%page cached="True" cache_type="memory"/>
<%include>
只需要傳遞一個參數就可以調用該參數對應的模板.
Also accepts arguments which are available as <%page> arguments in the receiving template:
<%include file="header.mako"/>
Welcome to OpenERP
<%include file="footer.mako"/>
<%include file="toolbar.html" args="current_section='members', username='ed'"/>
<%inherit>
Inherit allows templates to arrange themselves in inheritance chains.
When using the %inherit tag, control is passed to the topmost inherited template first, which then decides how to handle calling areas of content from its inheriting templates.
<%inherit file="index.mako"/>
<%def>
The %def tag defines a Python function which contains a set of content, that can be called at some other point in the template.
The %def tag is a lot more powerful than a plain Python def, as the Mako compiler provides many extra services with %def that you wouldn’t normally have, such as the ability to export defs as template “methods”, automatic propagation of the current Context, buffering/filtering/caching flags, and def calls with content, which enable packages of defs to be sent as arguments to other def calls (not as hard as it sounds).
<%def name="my_function(x)">
this is function ${x}
<%def>
<%namespace>
%namespace is Mako’s equivalent of Python’s import statement.
這允許訪問所有的渲染函數及其它模板文件的元數據, plain Python modules, 甚至本地定義的函數包.
<%namespace file="test.mako" import="*"/>
<%doc>
處理多行內容:
<%doc>
多行內容
使用文檔標簽
</%doc>
更多的資料,請訪問訪官方文檔: http://www.makotemplates.org/docs/index.html