About
RSS

Bit Focus


模板之工 - Mako 上手篇

Posted at 2012-07-30 03:37:19 | Updated at 2018-05-25 13:25:40

简介

Mako 是一个 Python 模板程序. 用于给定一个字符串, 或给定一个文件, 使用 Python 对象值动态地替换其中的一部分内容.

可是使用 pip 或 easy_install 安装 Mako 库.
# pip install Mako
# easy_install Mako

使用

基本文本替换

安装完成后, 在交互环境中可以通过下面的代码来测试 Mako
>>> import mako.template
>>> print mako.template.Template('Hello, ${ what }!').render(what='Mako')
Hello, Mako!
上述代码中, 引入 Mako 模板模块, 并使用模板对字符串 Hello, ${ what }! 中的动态内容进行替换. 动态内容是形如 ${ what } 这样的 Mako 标记, 它表示将传递给 render 函数的字典中, what 对应的项的值替换这个标记. 因此上面的 render 结果便是 Hello, Mako!.

替换文件中的动态内容

更多的应用场景是将需要生成的内容写成一个文件模板 (如 HTML 页面), 读取这个页面并生成结果内容. 在当前目录下创建 hello-mako.html 文件, 内容如下
<html>
<body>
Dear ${ username }, welcome back!
并使用如下的 Python 代码
import mako.template
templ = mako.template.Template(filename='hello-mako.html')
print templ.render(username='Mako')
就能看到输出的结果 HTML 代码了.

使用中文及指定编码

上面的页面模板代码中如果包含中文或其它非 ASCII 字符, 如
<html>
<body>
你好, ${ username }, 欢迎回来!
那么这一段程序在构造 mako.template.Template 对象时多半会挂掉. 要为 Mako 模板指定输入编码方式才行
import mako.template
templ = mako.template.Template(filename='hello-mako.html', input_encoding='utf-8')
print templ.render(username=u'柑奈')

分支

接下来, 如果这个用户是个管理员用户, 那么希望为这个用户呈现一个后台管理的入口 (当然其它用户就没这个福利了), 那么可以用 Mako 提供的分支来实现
你好, ${ username }, 欢迎回来!

%if is_admin:
    <a href='/admin'>管理页面</a>
%endif
并使用如下语句分别测试
templ = mako.template.Template(filename='hello-mako.html', input_encoding='utf-8')
print templ.render(username=u'柑奈', is_admin=False)
print templ.render(username=u'柑奈', is_admin=True)
%if %endif 之间表示一段分支. 如果确实需要书写一个百分号, 而不是作为 Mako 的指令符号, 那么此处须连续两个百分号 %% 来转义, 通常页面上似乎也不会出现那么多百分号, 所以这个应该还是可以接受的吧.

关于分支, 更详细的例子是
%if condition_a:
    do_a
%elif condition_b:
    do_b
%else:
    do_c
%endif

对象式引用

上面的例子中出现了两个模板参数 usernameis_admin. 当然这两个参数可能同为一个 user 对象的两枚属性, 因此, 实际上可以向模板传递一个参数 user, 而 usernameis_admin 以其属性形式给出. 如此的话, 上面的页面模板可以改成
<html>
<body>
Dear ${ user.username }, welcome back!

%if user.is_admin:
    <a href='/admin'>Admin</a>
%endif
在生成该模板时使用下面的代码
class User:
    def __init__(self, username, is_admin):
        self.username = username
        self.is_admin = is_admin

templ = mako.template.Template(filename='hello-mako.html', input_encoding='utf-8')
print templ.render(user=User(u'柑奈', False))

循环

如果该用户登入之后, 需要一个列表来显示该用户最近收到的消息, 这些消息也可以作为模板参数注入到页面中, 不过注入的不是一个对象, 而是一个列表的对象, 假定这些消息有 id, title 等属性, 那么
Dear ${ user.username }, welcome back!

%if user.is_admin:
    <a href='/admin'>Admin</a>
%endif

<ul>
%for m in messages:
    <li><a href='/msg?id=${m.id}'>${m.title}</a></li>
%endfor
</ul>
这样使用一个 for 循环就能搞定. for 循环的语法是
%for 每次迭代的对象 in 列表参数:
    循环输出的内容
%endfor
对应的 Python 代码类似下面这样
class Message:
    def __init__(self, id, title):
        self.id = id
        self.title = title

templ = mako.template.Template(filename='hello-mako.html', input_encoding='utf-8')
print templ.render(user=User(u'柑奈', False),
                   messages=[Message(0, 'Abc'), Message(1, 'Def')])

HTML 字符串转义

当然上面有安全隐患, 比如某个用户发了个消息, 标题是一段恶意 HTML 代码, 那么收信用户登录上来就被 XSS 了. 这时就要用到 HTML 转义. 在 Mako 里可以使用下面的语法来 HTML 转义
<li><a href='/msg?id=${m.id}'>${m.title | h}</a></li>
只需要在参数引用后面加上竖线跟 h 就行. 此外 Mako 还支持常用的 urlencoding, 写法如 ${m.id | u}.

这里仅列举 Mako 的常见功能. 更详细的请参阅 Mako 模板语法手册.

Post tags:   Python  Tutorial  Template  Mako

Leave a comment:




Creative Commons License Your comment will be licensed under
CC-NC-ND 3.0


. Back to Bit Focus
NijiPress - Copyright (C) Neuron Teckid @ Bit Focus
About this site