Python模板-Mako
一直使用Jinja2,前段时间听说mako,一试
大同小异,天下模板都差不多
要写代码测试,文档先行
资源
官网 http://www.makotemplates.org/
文档 http://docs.makotemplates.org/en/latest/
文档翻译 Mako模板入门 http://help.42qu.com/code/mako.html
安装
pip install mako
HelloWorld
from mako.template import Template
mytemplate = Template("hello world!")
print mytemplate.render()
-------------------------
from mako.template import Template
print Template("hello ${data}!").render(data="world")
语法
输出变量 ${x}
数学计算 ${1+1}
the contents within the ${} tag are evaluated by Python directly, so full expressions are OK
filter
${"test"|u}
${"test"|u,trim}
内置filter列表
u : URL escaping, provided by urllib.quote_plus(string.encode('utf-8'))
h : HTML escaping, provided by markupsafe.escape(string)
x : XML escaping
trim : whitespace trimming, provided by string.strip()
entity : produces HTML entity references for applicable strings, derived from htmlentitydefs
unicode (str on Python 3): produces a Python unicode string (this function is applied by default)
decode.<some encoding> : decode input into a Python unicode with the specified encoding
n : disable all default filtering; only filters specified in the local expression tag will be applied.
分支
% if x == 5:
abcd
% endif
循环
% for a in ['1', '2', '3']:
% if a == '1':
abc
% elif a == '2':
def
% else:
gh
% endif
$ endfor
Python语法
this is a template
<%
x = db.get_resource('foo')
y = [z.element for z in x if x.frobnizzle==5]
%>
% for elem in y:
element: ${elem}
% endfor
换行
加 / 强制不换行
设置变量
% for item in ('apple', 'banana'):
<%
isBanana = False
%>
% if item == 'banana':
<%
isBanana = True
%>
%endif
% if isBanana:
<span> Bought a banana</span>
%endif
%endfor
注释
## 这是一个注释.
...text ...
多行
<%doc>
这里是注释
更多注释
</%doc>
模块级别语句
<% %> 的一个变体是 <%! %>,代表模块级别的代码块。其中的代码会在模板的模块级别执行,而不是在模板的 rendering 函数中。
<%!
import mylib
import re
def filter(text):
return re.sub(r'^@', '', text)
%>
标签
定义了当前模板的总体特性,包括缓存参数,以及模板被调用时期待的参数列表(非必须)
<%page args="x, y, z='default'"/>
<%page cached="True" cache_type="memory"/>
<%include file="header.html"/>
hello world
<%include file="footer.html"/>
%def 标签用于定义包含一系列内容的一个 Python 函数,此函数在当前模板的其他某个地方被调用到
<%def name="myfunc(x)">
this is myfunc, x is ${x}
</%def>
${myfunc(7)}
<%block filter="h">
some <html> stuff.
</%block>
<%block name="header">
<h2><%block name="title"/></h2>
</%block>
Mako 中的 %namespace 等价于 Python 里的 import 语句。它允许访问其他模板文件的所有 rendering 函数和元数据
<%namespace file="functions.html" import="*"/>
<%inherit file="base.html"/>
处理多行注释:
<%doc>
these are comments
more comments
</%doc>
该标签使得 Mako 的词法器对模板指令的常规解析动作停止,并以纯文本的形式返回其整个内容部分
<%text filter="h">
heres some fake mako ${syntax}
<%def name="x()">${x}</%def>
</%text>
有时你想中途停止执行一个模板或者 <%def> 方法,只返回已经收集到的文本信息,可以通过在 Python 代码块中使用 return 语句来完成
% if not len(records):
No records found.
<% return %>
% endif
文件template
为提高性能,从文件中加载的 Template, 可以将它产生的模块的源代码以普通 python 模块文件的形式(.py),
缓存到文件系统中。只要加一个参数 module_directory 即可做到这一点:
from mako.template import Template
mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules')
print mytemplate.render()
当上述代码被 render 的时候,会创建文件 /tmp/mako_modules/docs/mytmpl.txt.py.
下一次 Template 对象被用同样参数调用的时候,就会直接重用该模块文件。
文件TemplateLookup
#有一个对 header.txt 文件的包含引用。而从何处去查找 header.txt, 则由 TemplateLookup 指明,是 "/docs" 目录
from mako.template import Template
from mako.lookup import TemplateLookup
mylookup = TemplateLookup(directories=['/docs'])
mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup)
--------------
#可以直接通过 TemplateLookup 来获取模板对象,利用 TemplateLookup 的 get_template 方法,
#并传递模板的 URI 作为参数
mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace')
mytemplate = mylookup.get_template("foo.txt")
print mytemplate.render()
-------------
参数
mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace', , collection_size=500)
TemplateLookup 同时也会在内存中缓存一组模板,所以并不是每一次请求都会导致模板的重新编译和模块重新加载。默认 TemplateLookup 的大小没有限制,但你可以通过 collection_size 参数来限制它
以上的 lookup 会持续加载模板到内存中,直到达到 500 的时候,它就会清除掉一定比例的模板缓存项,根据“最近最少访问”原则
另一个 TemplateLookup 相关的标志是 filesystem_checks. 默认为 True,
每一次 get_template() 方法返回模板后,原始的模板文件的 revision time 会和上次加载模板的时间做对比,
如果文件更新,则会加载其内容,并重新编译该模板。
在生产环境下,设置 filesystem_checks 为 False 可以带来一定的性能提升(和具体的文件系统有关)
自己创建context
from mako.template import Template
from mako.runtime import Context
from StringIO import StringIO
mytemplate = Template("hello, ${name}!")
buf = StringIO()
ctx = Context(buf, name="jack")
mytemplate.render_context(ctx)
print buf.getvalue()
其他
1.解决mako中文乱码问题
TemplateLookup(... , output_encoding='utf-8', ...)
Template(..., input_encoding='utf-8')
又在mako的模板文件的首行添加
## -*- encoding:utf8 -*-
The end. 未完待续
wklken
2013-12-14