Sunday, December 1, 2013
mako二三事 -- 函数二
五、调用其他模板中的函数
mako也能支持调用其他模板中的函数,因此,多个函数可以集合成一个mako函数库。不过mako仅支持顶层函数的跨模块调用,而且需要通过namespace标签来引入,例如,在mystuff.html中定义了一个函数account:
<%namespace name="mystuff" file="mystuff.html"/>
如上定义之后,就可以使用
${mystuff.account()}
来调用该函数了。这种方式看起来跟python中的import XXX as XXX 是一致的。不过mako的实现还是不一样的,我们来看一下这个模板编译之后的代码:
def _mako_get_namespace(context, name):
try:
return context.namespaces[(__name__, name)] # namespace缓存机制,如果已经存在,不需要再载入这个namespace
except KeyError:
_mako_generate_namespaces(context)
return context.namespaces[(__name__, name)]
def _mako_generate_namespaces(context):
# SOURCE LINE 3 # namespace语句对应的生成语句,每个namespace语句分别生成。
ns = runtime.TemplateNamespace(u'mystuff', context._clean_inheritance_tokens(), templateuri=u'mystuff.html', callables=None, calling_uri=_template_uri)
context.namespaces[(__name__, u'mystuff')] = ns # 将namespace缓存到context中
def render_body(context,**pageargs):
__M_caller = context.caller_stack._push_frame()
try:
__M_locals = __M_dict_builtin(pageargs=pageargs)
mystuff = _mako_get_namespace(context, 'mystuff’) # 从namespace中取得该函数,即可使用
__M_writer = context.writer()
# SOURCE LINE 2
__M_writer(u'\n')
# SOURCE LINE 3
__M_writer(u' \n')
# SOURCE LINE 4
__M_writer(unicode(mystuff.account())) # 函数调用
__M_writer(u'\n')
return ''
finally:
context.caller_stack._pop_frame()
python支持from XXXX import XX, XXX这种import方式,mako也支持类似方式,如:
<%namespace file="mystuff.html" import="foo, bar"/>
<%namespace file="mystuff.html" import=“*"/>
六、在python中调用模板函数
mako支持通过python程序来调用模板函数,这种方式在某些特定场合可以使用。如:
from mako.template import Template
template = Template("""
<%def name="hi(name)">
hi ${name}!
</%def>
<%def name="bye(name)">
bye ${name}!
</%def>
""")
print template.get_def("hi").render(name="ed")
print template.get_def("bye").render(name="ed")
七、嵌套函数
mako也可以像python一样支持嵌套函数,而且其作用也跟python中的一模一样,编译成py文件后也是嵌套函数,因此其中变量的作用域也跟python中的类似。注意,内嵌的函数不能被其他模块引用。
<%
x = 12
%>
<%def name="outer()">
<%
y = 15
%>
<%def name="inner()">
inner, x is ${x}, y is ${y}
</%def>
${inner()}
outer, x is ${x}, y is ${y}
</%def>
${outer()}
输出:
inner, x is 12, y is 15
outer, x is 12, y is 15
在上面代码中,还需要注意的一点是,这里的x并不会生成一个全局的变量,在模板里写的所有内容都会被包括在一个叫render_body的函数里面,如果需要在多个模板之间传递、共享一些数据需要使用特殊的技巧,这个在Context里面会讲到。
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment