八 、mako中def的一些特定参数
前面我们就提到过,mako的函数是一种增强性的函数,除了可以往函数中传递参数之外,还可以为该函数定义一些额外的参数。例如,
1. cache
我们可以为一个mako函数单独定义一个cache,设定cache过期时间。
<%def name="somedef()"cached="True" cache_timeout="60">
<%
import time
%>
time = ${time.time()}
</%def>
${somedef()}
2. buffer
在写mako模板的时候,要牢牢记住的一点是:不论是否在函数内,模板内容都是直接写到输出的。也就是说,所有函数,不做特殊处理的话,它的返回值都是空字符串。这在平常可能不会注意到,但如果遇到类似如下的用法的时候就会有问题:
${" results " + somedef() + " more results"}
上面的${}中是一个表达式,这在mako中是合法的。如果这里的somedef函数输出somedef's results字符串,那我们会得到如下结果:
somedef's results results more results
这是因为,在函数somedef运行时,其运行结果就已经写到 输出中了。然后,somedef返回'',最后" results " + ''+ " more results"结果求值之后输出,这就是上面这个结果。
有的时候,我们希望将somedef这个函数的运行结果先暂存起来,经过一定处理之后,再写入到输出中。因此,mako引入了buffered这个参数来解决这个问题。(注意,这里的buffer跟cache是完全不同的概念。)
<%def name="somedef()" buffered="True">
somedef's results
</%def>
${" results " + somedef() + " more results"}
输出:
results somedef's results more results
我们来看一下这种方式生成的py文件:
def render_somedef(context):
__M_caller = context.caller_stack._push_frame()
try:
context._push_buffer()
__M_writer = context.writer()
# SOURCE LINE 1
__M_writer(u"\n somedef's results\n")
finally:
__M_buf = context._pop_buffer()
context.caller_stack._pop_frame()
return __M_buf.getvalue()
可以看到,该函数创建了一个暂存区,然后将其中的数据作为了return的返回值。
如果只是希望临时性的获取一下mako函数运行结果进行一些测试,而不是直接buffer起来,mako也提供了一个叫capture的方法。通过capture,可以截获一个普通的mako的运行结果,转成返回值。例如
<%def name="somedef(age=8, weight=100)">
somedef's results ${age} ${weight}
</%def>
${" results " + capture(somedef, 10, weight=120) + " more results"}
输出:
results somedef's results 10 120 more results
3. filter
mako本身是一个模板,因此也就带了一系列的filter,通过这些filter的作用,可以很灵活的将数据转换成特定的格式。在mako定义函数时,也引入了filter概念。注意,因为需要filter,也就必须要截获函数的运行结果,因此,filter默认也带有buffer功能。例如
<%def name="foo()" filter="h, trim">
this is bold
</%def>
${foo()}
输出为:
<b>this is bold</b>
这里需要注意的是,filter是def的参数,不是foo的参数。这个filter仅仅作用于该函数的生成结果。
4. Decorating
除了filter之外,mako还提供了Decorating的功能,不过因为模板的特殊性,mako函数的Decorating跟python中的还是有很多区别的。例如
<%!
def bar(fn):
def decorate(context, *args, **kw):
context.write("BAR")
fn(*args, **kw)
context.write("BAR")
return 'mytest'
return decorate
%>
<%def name="foo()" decorator="bar">
this is foo
</%def>
${"abc"+foo()}
输出:
BAR
this is foo
BARabcmytest
注意:
a. mako里面所有的函数第一个参数都是context,所以 decorate函数的第一个参数必须是context。
b. 如果希望在decorate输出内容,可以使用context.write函数,这也是mako推荐的方式。
c. 这里的decorate应该返回'',像上示例中返回其他内容的话会加到输出结果中去,但要注意加入的位置。
d. 如果用template.get_def('somedef').render()之类的方法来渲染模板,则只会使用context.write的结果,抛弃return返回值。
>>> print template.get_def("foo").render()
BAR
this is foo
BAR
另外,capture函数也可以用于构建decorate,例如:
<%!
def bar(fn):
def decorate(context, *args, **kw):
return "BAR" + runtime.capture(context, fn, *args, **kw) + "BAR"
return decorate
%>
<%def name="foo()" decorator="bar">
this is foo
</%def>
${foo()}
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment