代码改变世界

mako的def和block(2)

2012-07-27 13:31  ubunoon  阅读(1356)  评论(0编辑  收藏  举报

mako模板的中def和block,都是可以调用的函数,def更多类似python的def,block更多的是面向布局的。

 

def基础

def需要一个name属性,如

<%def name="hello()">

  hello world

</%def>

 

调用用下面的方式

the def: ${hello()}

 

如果<%def>没有在<%def>中嵌套,就是所谓的顶层def,所有的def可以当前上下文中调用。

 

由于def是python的函数,所有可以定义和传递参数,需要符合普通的python函数规范

 

 

来自其他文件def调用

顶层的<%def>可以导出到其他模板模块中,类似用<%include>方式来进行其他模板的<%def>调用。

导入其他模板,

<%namespace name="mystuff" file="mystuff.html">

然后mystuff就会到当前的scope中,然后调用mystuff

${mystuff.somedef(x=5,y=7)}

 

<%namespace>标签页支持python的import语句

<%namespace file="mystuff.html" import="foo, bar" />

 

 

调用def编程

可以在Template对象用get_def获取DefTemplate对象。

 

def嵌套

    在此处,mako官方给出两个非常有趣的例子

<%
    x = 12
%>
<%def name="outer()">
<%
        y = 15
    %>
<%def name="inner()">
        inner, x is ${x}, y is ${y}
</%def>

    outer, x is ${x}, y is ${y}
</%def>


<%
    x = 10
%>
<%def name="somedef()">
    ## error !
    somedef, x is ${x}
<%
        x = 27
    %>
</%def>


第二个列子中,x将会引用局部变量的那个x,此时x还未赋值,会报错!

 

 

 

在嵌入内容或者其他Def中调用def

可以通过<%namespace:defname>来扩展自定义的tag系统,大部分情况下local或者self表示当前的模板namespace。

 

当目标def已经卷入进来时,caller变量用来代替该出内容,caller包含另外的含body和def定义的namespace。body内部用方法body()来引入。

 

<%def name="buildtable()">
    <table>
        <tr><td>
${caller.body()}
        </td></tr>
    </table>
</%def>

<%self:buildtable>
    I am the table body.
</%self:buildtable>

此时的caller用来替换<%self:buildtable>,注意self后面的名称与def定义的名称要一致。

官方还提供了下面的例子:
<%def name="lister(count)">
    % for x in range(count):
${caller.body()}
    % endfor
</%def>

<%self:lister count="${3}">
    hi
</%self:lister>

count="${3}"使得用来提供的3会被当成表达式处理,从而得到整形的3,而不是字符串3,这个range的参数必须是整形决定的。


注意body函数也可以传递参数
  

Bocks
<%block>标签类似<%def>,匿名的block在局部render中可用,命名的block行为类似Jinja2的block标签,
与def的差别:
1、block声明不允许参数参数签名
2、命名block仅在一个模板中定义一次,如果有同名的则出错,如果有同名的def,也会出错。
3、命名的block不能再def中定义或者内部的body调用。

为了能够使得命名block可以共享page的参数,使用args属性,类似的**pageargs变量也存在命名的blocks,这个参数在page标签中不是显式存在的。