Thursday, December 12, 2013

mako二三事 -- Blocks一

 除了函数,mako还提供了一种特殊的结构 — Block。在很大程度上,Block跟Def非常相似,但作为模板,需要构建灵活多变的页面结构,Block又有着一些Def所不具备的特殊特性。

一、Block的使用

block跟def最大的一个区别就是def在定义之后需要专门去调用它才会生效,block不需要,block定义之后就会默认在该定义处生效渲染。正因为这种特性,block就可以匿名使用。例如:

<html>
    <body>
        <%block>
            this is a block.
        </%block>
    </body>
</html> 

将会生成

<html>
    <body>
            this is a block.
    </body>
</html> 

该block的定义如果使用def来表达的话,等同于:

<html>
    <body>
        <%def name="testblock()">
            this is a block.
        </%def>${testblock()}
    </body>
</html>

尽管在用法上与def有所不同,def上的一些比较有用的参数还是可以在block上使用的,如:

<html>
    <body>
        <%block filter="h">
            this is some escaped html.
        </%block>
    </body>
</html>

<html>
    <body>
        <%block cached="True" cache_timeout="60">
            This content will be cached for 60 seconds.
        </%block>
    </body>
</html> 

% for i in range(1, 4):
    <%block>i is ${i}</%block>
% endfor

我们再来看一下第一段block模板生成的代码:

def render_body(context,**pageargs):
    __M_caller = context.caller_stack._push_frame()
    try:
        __M_locals = __M_dict_builtin(pageargs=pageargs)
        def __M_anon_4():                    # 跟def类似,block块在python中生成的代码也是一个内嵌函数
            __M_caller = context.caller_stack._push_frame()
            try:
                __M_writer = context.writer()
                # SOURCE LINE 4
                __M_writer(u'\n            this is a block.\n        ')
                return ''
            finally:
                context.caller_stack._pop_frame()
        __M_writer = context.writer()
        # SOURCE LINE 1
        __M_writer(u'\n\n    \n        ')
        __M_anon_4()               # 调用block
        # SOURCE LINE 6
        __M_writer(u'\n    
\n\n')        return ''
    finally:
        context.caller_stack._pop_frame() 

因为这里使用了匿名block,所以名字为anon加一个递增数字。同样的,匿名函数不支持其他地方调用,所哟没有生成一个render_XXX函数。

No comments:

Post a Comment