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标签中不是显式存在的。