Python模板库Mako的用法

Mako是一个高性能的Python模板库,它的语法和API借鉴了不少其余的模板库,如Django、Jinja2等等。css

基本用法

建立模板并渲染它的最基本的方法是使用 Template 类:html

传给 Template 的文本参数被编译为一个Python模块。模块包含一个 render_body() 函数,它产生模板的输出。调用 render() 方法时,Mako创建了一个模板的运行环境,并调用 render_body() 函数,把输出保存到缓冲,返回它的字符串内容。
render_body() 函数中能够访问一个变量集。能够向 render() 方法发送额外的关键词参数来指定这些变量:git

ender() 方法使Mako建立一个 Context 对象,它存储模板能够访问的全部变量和一个用来保存输出的缓冲。也能够本身建立 Context ,用 render_context() 方法使模板用它来渲染:github

使用文件模板

Template 也能够从文件加载模板,使用 filename 参数:web

为了提升性能,从文件加载的 Template 还能够在文件系统中将生成的模块缓存为通常的Python模块文件(.py文件),这经过添加 module_directory 参数实现:django

上面的代码渲染后,会建立一个/tmp/mako_modules/docs/tpl.txt.py文件,其中包含模块的源代码。下次一样参数的 Template 建立时,自动重用这个模块文件。缓存

使用TemplateLookup

到如今的例子都是有关单个 Template 对象的用法。若是模板中的代码要定位其余模板资源,须要某种使用URI来找到它们的方法。这种需求是由 TemplateLookup 类来达到的。这个类经过传入一个模板查找目录的列表来构造,而后做为关键词参数传给 Template 对象:app

上面建立的模板中包含文件header.txt。为了查找header.txt,传了一个 TemplateLookup 对象给它。
一般,应用会以文本文件形式在文件系统上存储大部分或所有的模板。一个真正的应用会直接从 TemplateLookup 取得它的模板,使用 get_template() 方法,它接受须要的模板的URI做为参数:ide

面的例子中咱们建立了一个 TemplateLookup ,它从/docs目录中查找模板,并把全部的模块文件存储到/tmp/mako_modules目录中。经过将传入的URI附加到每一个查找目录来定位模 板,如传递/etc/beans/info.txt,将查找文件/docs/etc/beans/info.txt,若是没找到将抛出 TopLevelNotFound 异常。
当定位到模板的时候,传给 get_template() 调用的URI也会做为 Template 的 uri 属性。 Template 使用这个URI来获得模块文件的名字,所以上面的例子中对/etc/beans/info.txt会建立模块文件/tmp/mako_modules /etc/beans/info.txt.py。函数

设置收集的大小

TemplateLookup 还知足将内存中缓存的模板总数设为一个固定的值。默认状况 TemplateLookup 大小是不限的。能够用 collection_size 参数指定一个固定值:

上面的 lookup 将模板加载到内存中的上限是500个。以后,它将使用LRU策略来清理替换模板。

设置文件系统检查

TemplateLookup 的另外一个重要标志是 filesystem_checks 。默认为 True ,每次 get_template() 方法返回一个模板,会比较原始模板文件的修改时间和模板的最近加载时间,若是文件更新,就从新加载和编译模板。在生产系统中,将 filesystem_checks 设为 False 能得到一些性能的提高。

使用Unicode和编码

Template 和 TemplateLookup 能够设置 output_encoding 和 encoding_errors 参数来将输出编码为Python支持的编码格式:

使用Python 3时,若是设置了 output_encoding , render() 方法将返回一个 bytes 对象,不然返回 string 。
render_unicode() 方法返回模板输出为Python unicode 对象,Python 3为 string :

上面的方法没有输出编码的参数,能够自行编码:

注意Mako中模板的底层输出流是Python Unicode对象。

处理异常

模板异常可能发生在两个地方。一个是当你查找、解析和编译模板的时候,一个是运行模板的时候。模板运行中发生的异常会正常在产生问题的Python代码处 抛出。Mako有本身的一组异常类,它们主要用于模板构造的查找和编译阶段。Mako提供了一些库例程用来对异常栈提供Mako的信息,并将异常输出为文 本或HTML格式。Python文件名、行号和代码片断会被转换为Mako模板文件名、行号和代码片断。Mako模板模块的行会被转换为原始的模板文件对 应行。

text_error_template() 和 html_error_template() 函数用于格式化异常跟踪。它们使用 sys.exc_info() 来获得最近抛出的异常。这些处理器的用法像下面这样:

html_error_template() 模板接受两个选项:指定 full=False 只渲染HTML的一节,指定 css=False 关闭默认的样式表。如:

HTML渲染函数也能够用 format_exceptions 标志加到 Template 中。这种状况下,模板在渲染阶段的任何异常在输出中的结果都会替换为 html_error_template() 的输出:

注意上面模板的编译阶段发生在构造 Template 时,没有定义输出流。所以查找、解析、编译阶段发生的异常正常状况下不会被处理,而是传播下去。渲染前的追溯不包括Mako形式的行,这意味着渲染前和渲 染中发生的异常会用不一样的方式处理,所以 try/except 可能更经常使用。

错误模板函数使用的底层对象是 RichTraceback 对象。这个对象也能够直接用来提供自定义的错误视图。下面是一个用法的样例:

集成Mako

在Django中集成Mako

经过Django的中间件能够集成Mako。首先须要安装django-mako模块。
在Django项目的settings.py文件中,修改 MIDDLEWARE_CLASSES ,添加 djangomako.middleware.MakoMiddleware 。使用 render_to_response() 函数便可使用:

在Tornado中集成Mako

在Tornado中能够直接使用Mako,下面是一个使用示例:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import tornado.web
 
import mako.lookup
 
import mako.template
 
LOOK_UP mako.lookup.TemplateLookup(
 
         directories=[TEMPLATE_PATH]module_directory='/tmp/mako',
 
         output_encoding='utf-8'encoding_errors='replace')
 
class BaseHandler(tornado.web.RequestHandler):
 
     def initialize(selflookup=LOOK_UP):
 
         '''Set template lookup object, Defalut is LOOK_UP'''
 
         self._lookup lookup
 
     def render_string(selffilename**kwargs):
 
         '''Override render_string to use mako template.
 
        Like tornado render_string method, this method
 
        also pass request handler environment to template engine.
 
        '''
 
         try:
 
             template self._lookup.get_template(filename)
 
             env_kwargs dict(
 
                 handler self,
 
                 request self.request,
 
                 current_user self.current_user,
 
                 locale self.locale,
 
                 self.locale.translate,
 
                 static_url self.static_url,
 
                 xsrf_form_html self.xsrf_form_html,
 
                 reverse_url self.application.reverse_url,
 
                 )
 
             env_kwargs.update(kwargs)
 
             return template.render(**env_kwargs)
 
         except:
 
             # exception handler
 
             pass
 
     def render(selffilename**kwargs):
 
         self.finish(self.render_string(filename**kwargs))
相关文章
相关标签/搜索