Mako 模板系统文档翻译(1) 使用基础

译者的前言(木野狐 http://rchen.cnblogs.com):

Mako 是一个模板引擎,快速而强大。其语法类似于 Python,可以在模板内随时建立可复用的函数,灵活性比较高。让我想起来最初学习写 ASP 的感觉。
Mako 的主页地址:http://www.makotemplates.org/docs/usage.html

相比而言,Django 内建的模板引擎,为了维持所谓模板语法的纯粹性和简单性,更纯粹的满足 MVC 模式的规定,牺牲了很多灵活性,一些高级的功能不得不利用 tag 和 filter 来实现,其写法并不太方便。而我前一阵为此事苦恼过,曾经想如何在 Django 中借鉴一点 Karrigell 那样自由的 pih 方式,但自己时间太少最终又不了了之。

因此,将 Mako 集成到 Django 中,以取代 Django 自带的模板引擎,也许是一个不错的办法。可以提高模板的灵活性和可操作性。在这方面,已经有黄毅和 limodou 所作的不少努力:
http://blog.donews.com/limodou/archive/2007/06/14/1175409.aspx

而我目前想做的工作是翻译一下 Mako 的文档。下面开始文档正文。

------------------------------------------------------------------------

原文http://www.makotemplates.org/docs/usage.html
译文

Version: 0.1.5 Last Updated: 05/01/07 20:21:35

使用基础

这一节介绍 Mako template 的 Python API. 如果你在 Pylons 之类的 web 框架中使用 Mako,那么集成 Mako API 的工作也许已经给你做好了。你可以直接跳到下一节,语法

最简单的办法是通过 Template 类,创建模板并渲染之:

from mako.template import Template

mytemplate = Template("hello world!")
print mytemplate.render()

上述例子中,传递给 Template 的文本参数被编译成了一个 python 的模块。该模块有一个 render_body() 函数,用于输出模板内容。当 mytemplate.render() 被调用时,Mako 会为此模板创建起一个运行时环境,并调用 render_body() 函数,然后捕获其输出到缓冲区,然后返回其字符串内容。

render_body() 函数中的代码可以访问包含了一些变量的一个名称空间。你可以传递额外的关键字参数给 render() 方法,这些参数将转化为可被访问的变量:

from mako.template import Template

mytemplate = Template("hello, ${name}!")
print mytemplate.render(name="jack")

template.render() 方法会让 Mako 创建一个 Context 对象,其中包含了所有该模板可访问的变量的名称,以及一个用于捕获输出的缓冲区。你也可以自己创建 Context 对象,并命令模板利用此 Context 来 render,用 render_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()

使用基于文件的模板

你也可以从文件中加载 Template 的内容,使用 filename 关键字参数: 

from mako.template import Template

mytemplate = Template(filename='/docs/mytmpl.txt')
print mytemplate.render()

为提高性能,从文件中加载的 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

在模板中,我们有时候需要调用或引用其他模板的内容,这就牵涉一个模板查找定位的问题,通常用简单的 URI 字符串来定位。我们用 TemplateLookup 类来负责这个任务。该类的构造函数需要传递一系列可供查找模板的路径的列表。然后我们再将此 TemplateLookup 对象用关键字参数的形式传递给 Template 对象。

from mako.template import Template
from mako.lookup import TemplateLookup

mylookup = TemplateLookup(directories=['/docs'])
mytemplate = Template("""<%include file="header.txt"/> hello world!""", 
    lookup=mylookup)

上述例子中创建了一个文本模板,其中有一个对 header.txt 文件的包含引用。而从何处去查找 header.txt, 则由 TemplateLookup 指明,是 "/docs" 目录。

通常,应用程序会把模板用文本文件的形式保存在文件系统中。而为了方便起见,我们可以直接通过 TemplateLookup 来获取模板对象,利用 TemplateLookup 的 get_template 方法,并传递模板的 URI 作为参数:

from mako.template import Template
from mako.lookup import TemplateLookup

mylookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules')

def serve_template(templatename, **kwargs):
    mytemplate = mylookup.get_template(templatename)
    print mytemplate.render(**kwargs)

lookup 在查找模板时通过向其中的每一个搜索路径附加我们提供的模板 URI 的方式,来尝试获取模板文件。如果找不到则引发 TopLevelNotFound 异常,这是一个 Mako 的自定义异常类型。
当 lookup 找到模板时,它还会给 Template 指定一个 uri 属性,这个 uri 就是传递给 get_template() 方法的参数。Template 可以用此 uri 来计算出其对应的模块文件的名称。比如在上述例子中,/etc/beans/info.txt 这个 URI 名称参数,会导致创建模块文件 /tmp/mako_modules/etc/beans/info.txt.py.

设定集合的大小

TemplateLookup 同时也会在内存中缓存一组模板,所以并不是每一次请求都会导致模板的重新编译和模块重新加载。默认 TemplateLookup 的大小没有限制,但你可以通过 collection_size 参数来限制它:

mylookup = TemplateLookup(directories=['/docs'], 
                module_directory='/tmp/mako_modules', collection_size=500)

以上的 lookup 会持续加载模板到内存中,直到达到 500 的时候,它就会清除掉一定比例的模板缓存项,根据“最近最少访问”原则。

设置文件系统检查

另一个 TemplateLookup 相关的标志是  filesystem_checks. 默认为 True, 每一次 get_template() 方法返回模板后,原始的模板文件的 revision time 会和上次加载模板的时间做对比,如果文件更新,则会加载其内容,并重新编译该模板。在生产环境下,设置 filesystem_checks 为 False 可以带来一定的性能提升(和具体的文件系统有关)。

使用 Unicode 和 Encoding

Template 和 TemplateLookup 都可以接受 output_encodingencoding_errors 参数,用来对输出以 Python 支持的任何方式进行编码:

from mako.template import Template from mako.lookup import TemplateLookup mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8',

encoding_errors='replace') mytemplate = mylookup.get_template("foo.txt") print mytemplate.render()

另外,render_unicode() 方法可以将模板的输出转换为一个 Python 的 Unicode 对象返回:

print mytemplate.render_unicode()

上面的方法调用未提供输出编码参数,你可以通过下列语法来进行编码:

print mytemplate.render_unicode().encode('utf-8', 'replace')

注意, Mako 能将数据返回为任何 encoding 或 unicode 的能力暗示着,模板内部的输出流是一个 Python unicode 对象。这种行为的详细描述在 The Unicode Chapter.

处理异常

模板异常可能在两种截然不同的地方出现。第一种是当你查找,分析和编译模板时,另一种是当你运行模板的时候。
在模板的运行过程中,异常通常从产生问题的 python 代码出抛出。Mako 有其独立的一套异常类,它们大多数针对模板构造过程的查找和词法分析/编译阶段。Mako 还提供了一些库函数,这些函数用来帮助提供 Mako 相关的异常栈跟踪信息,并可用纯文本或 HTML 方式格式化异常信息。不管是哪种情况,这些处理函数的作用在于将 Python 文件名,行号,以及代码例子转换为 Mako 的模板文件名,行号,以及代码范例。在跟踪栈里对应于某个 Moko 模板的每一行,都回被转换为和源模板文件相关的。

为了格式化异常跟踪信息,系统提供了 text_error_template 和 html_error_template 函数。它们都利用了 sys.exc_info() 函数来获取最近抛出的异常信息。下面是常见的用法:

from mako import exceptions

try:
    template = lookup.get_template(uri)
    print template.render()
except:
    print exceptions.text_error_template().render()

如果使用 HTML 的输出函数:

from mako import exceptions

try:
    template = lookup.get_template(uri)
    print template.render()
except:
    print exceptions.html_error_template().render()

HTML 输出函数也内建到了 Template 中。通过 format_exceptions 这个标志位参数。这样,任何在 template 的 render 阶段引发的异常,都会使得 template 的输出内容被 html_error_template 方法的输出所替代。

template = Template(filename="/foo/bar", format_exceptions=True)
print template.render()

注意,上述模板的编译阶段发生在你构造 Template 对象本身的时候,并且没有定义输出流。所以,在查找/解析/编译阶段引发的异常不会被处理,而是像平常那样被继续抛出到更高层次的调用堆栈上(繁殖, propagate)。虽然 pre-render traceback 不会包含任何 Mako 特定的行,这意味着发生在 rendering 之前的异常,以及 rendering 过程中发生的异常,需要用不同的办法分别处理。因此,上面的 try/except 模式可能是比较通用的一种写法。

被错误模板函数使用的内部对象是 RichTraceback. 该对象也可以被直接用于提供自定义错误视图。下面是一个范例应用,可以描述其一般使用的 API:

from mako.exceptions import RichTraceback

try:
    template = lookup.get_template(uri)
    print template.render()
except:
    traceback = RichTraceback()
    for (filename, lineno, function, line) in traceback.traceback:
        print "File %s, line %s, in %s" % (filename, lineno, function)
        print line, "\n"
    print "%s: %s" % (str(traceback.error.__class__.__name__), traceback.error)

关于 RichTraceback 的更深入信息可以查阅 mako.exceptions 的模块级文档。

常见框架的集成

Mako 的发布包包含了一些帮助代码,用于在其他流行的 web 框架中使用 Mako 的场景。下面是其概述:

Turbogears/Pylons 插件

Turbogears 和 Pylons 使用的基础插件方法包含在模块 mako.ext.turbogears 中,使用 TGPlugin 类。This is also a setuptools entrypoint under the heading python.templating.engines with the name mako.

WSGI


在 examples/wsgi/run_wsgi.py 中,包含了一个 WSGI 程序的例子。该程序的目的是从 templates 以及 htdocs 目录中提取文件,并包含了一个初步的双文件布局。 WSGI 运行程序担任了一个功能齐全的 web 服务器的角色,使用 wsgiutils 来运行它自身,并把 GET 和 POST 参数信息从 request 中传递到 Context. 它可以服务图片,css 文件以及其它类型的文件。并可以使用 Mako 内建的异常处理函数来显示错误。

Pygments

A Pygments-compatible syntax highlighting module is included under mako.ext.pygmentplugin. This module is used in the generation of Mako documentation and also contains various setuptools entry points under the heading pygments.lexers, including mako, html+mako, xml+mako (see the setup.py file for all the entry points).

下一节: 语法 

 

posted on 2007-06-15 02:11  NeilChen  阅读(9190)  评论(5编辑  收藏  举报

导航