Tuesday, December 10, 2013

mako二三事 -- 函数四

九、def的其他的调用方式

mako中的函数不仅仅是函数,还有一种模板特有的调用方式。我们经常使用它来创建自定义标签:

1. 自定义标签

<%def name="buildtable()">
   

       
            ${caller.body()}
       
   
</%def>

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

输出:

   

       

    I am the table body.

       
   
 
self:buildtable 这种用法是mako0.2.3之后引入的一种用法,通过这种方式,可以创建任意的定制标签。在这段代码中,需要注意的是:
a. ${caller.body()}表示读取调用者的body部分内容,这里就是    I am the table body.
b. self为namespace,这里的self表示本模块。也可以是其他包含所需函数的模块名


2. 带参数的标签

函数可以带参数执行,做成自定义标签之后,也一样可以带入需要的参数,如:

<%def name="lister(count)">
    % for x in range(count):
        ${caller.body()}
    % endfor
</%def>

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

输出:
hi
hi
hi

这里的lister函数就带了一个叫count的参数,因此在调用的时候,使用count="${3}”传入该参数。这段代码需要注意的地方是这个函数需要的是一个整形,而参数的值需要用”"包含,因此我们使用了mako的表达式${3},这里表示传入了一个表达式,该表达式的值为3.


3. body参数

caller.body()输出的内容是调用者中间部分的模板内容,因此,我们也可以body传一个参数到这些模板内容里去。比如我们在body中传入一个参数caller.body(name=“cat"),那么在调用者模板内容中就可以用 hi ${name}来访问这个传入的参数。不过我们还需要在调用者那里也申明一下这个参数。例如:

<%def name="layoutdata(somedata)">
    <table>
    % for item in somedata:
        <tr>
        % for col in item:
            <td>${caller.body(col=col)}</td>
        % endfor
        </tr>
    % endfor
    </table>
</%def>

<%self:layoutdata somedata="${[[1,2,3],[4,5,6],[7,8,9]]}" args="col">\
Body data: ${col}\
</%self:layoutdata> 

输出:

    <table>
        <tr>
            <td>Body data: 1</td>
            <td>Body data: 2</td>
            <td>Body data: 3</td>
        </tr>
        <tr>
            <td>Body data: 4</td>
            <td>Body data: 5</td>
            <td>Body data: 6</td>
        </tr>
        <tr>
            <td>Body data: 7</td>
            <td>Body data: 8</td>
            <td>Body data: 9</td>
        </tr>
    </table>

这段代码中:
a. ${caller.body(col=col)}中定义了一个col的参数,将每次循环的col值传入其中。
b. args="col”申明了col参数
c. Body data: ${col}\使用col参数输出,这里的\表示模板不换行


4. 自定义方法

body是mako中内置的方法,其实我们还可以在调用者模板内容处自定义需要的函数供外面的函数使用。

<%def name="layout()">
    ## a layout def
    <div class="mainlayout">
        <div class="header">
            ${caller.header()}
        </div>

        <div class="sidebar">
            ${caller.sidebar()}
        </div>

        <div class="content">
            ${caller.body()}
        </div>
    </div>
</%def>

## calls the layout def
<%self:layout>
    <%def name="header()">
        I am the header
    </%def>
    <%def name="sidebar()">
        <ul>
            <li>sidebar 1</li>
            <li>sidebar 2</li>
        </ul>
    </%def>

        this is the body
</%self:layout> 

输出

    <div class="mainlayout">
       


        I am the header

        </div>

        <div class="sidebar">

        <ul>
            <li>sidebar 1</li>
            <li>sidebar 2</li>
        </ul>

        </div>

        <div class="content">




        this is the body

        </div>
    </div> 

在这个例子里,我们将调用者模板内容分成了三个部分,header、sidebar、以及剩下的body。因此我们就可以在layout函数中调用者三个函数。现在有模板特有的那种搭积木般的感觉了吧。只要把layout和调用者分别放入不同的文件中,layout就变成了一个页面框架的定义模板,不同的调用者可以使用这个公用的模板,而其中的内容各不相同。

No comments:

Post a Comment