模板库Mako的语法

Mako模板从一个包含各种类型的内容的文本流解析得到,包括XML、HTML、email文本等。模板还可以包含Mako指令,用来表示变量和表达式替换、控制结构、服务器端注释、整块Python代码,还有用来提供额外功能的各种标签。所有这些结构都被编译为实际的Python代码。这意味着你可以在Mako模板的每个方面都充分利用Python的强大能力。

目录

表达式替换

最简单的表达式是变量替换。语法为 ${} ,这是从Perl、Genshi、JSP EL等得到的启发:

this is x: ${x}

上面的例子会把 x 的字符串表示输出到模板的输出流。 x 通常来自于传递给模板渲染函数的 Context 。如果没有传入x 给模板,并且也没有本地赋值,那么就等于一个特殊的值 UNDEFINED 。

${} 标签中的内容由Python直接计算,因此也可以使用完整的表达式:

pythagorean theorem:  ${pow(x,2) + pow(y,2)}

表达式的结果都会在输出到输出流之前转换为字符串形式。

表达式转义

Mako有一组内建的转义机制,包括HTML、URI和XML转义,还有空白截断函数。这些转义可以用 | 操作添加到表达式替换:

${"this is some text" | u}

上面将URL转义应用到表达式上,生成 this+is+some+text 。 u 表示URL转义, h 表示HTML转义, x 表示XML转义, trim 为空白截断函数。

更多有关内建的过滤函数,包括如何编写自己的过滤函数,见 Filtering and Buffering 。

控制结构

控制结构指用来控制程序流的那些东西——条件(即 if/else )、循环(如 while 和 for )、还有 try/except 等。Mako中,控制结构写成 % 标记后面跟正常的Python控制表达式,用 % 加标签 end<name> 结束, <name> 为表达式的关键词:

% if x==5:
    this is some output
% endif

% 可以放在前面没有文本的行的任何地方,并且缩进是不敏感的。Python所有的“冒号”表达式都可以使用,包括if/elif/else 、 while 、 for ,甚至是 def ,不过对 def Mako有更好的内建标签。

% for a in [‘one‘, ‘two‘, ‘three‘, ‘four‘, ‘five‘]:
    % if a[0] == ‘t‘:
    its two or three
    % elif a[0] == ‘f‘:
    four/five
    % else:
    one
    % endif
% endfor

% 符号也可以被转义,如果你想在行首使用百分比符号,可以用 %% 来转义:

%% some text

    %% some more text

循环上下文

循环上下文提供 % for 结构中的循环的额外信息:

<ul>
% for a in ("one", "two", "three"):
    <li>Item ${loop.index}: ${a}</li>
% endfor
</ul>

参考 The Loop Context 。

注释

有两种形式的注释。单行注释在行首使用 ## :

## this is a comment.
...text ...

多行注释通过 <%doc> ...text... </%doc> :

<%doc>
    these are comments
    more comments
</%doc>

新行过滤器

行末的 \ 字符可以将下一行连接到当前行:

here is a line that goes onto another line.

上面的文本等价于:

here is a line that goes onto another line.

Python代码块

可以用 <% %> 标签引入任意Python代码块:

this is a template
<%
    x = db.get_resource(‘foo‘)
    y = [z.element for z in x if x.frobnizzle==5]
%>
% for elem in y:
    element: ${elem}
% endfor

在 <% %> 里面,可以写普通的Python代码块。代码的整体缩进不受限制,Mako编译器会根据生成的Python代码进行调节。

模块级的块

<% %> 的一个变种是模块级的块,用 <%! %> 表示。标签中的代码在模板的模块级别执行,而不是在模板的渲染函数中。因此,这些代码不能访问模板的上下文,并且只能在模板加载到内存时执行(一般每个应用一次,取决于运行环境)。使用 <%! %> 标签来声明模板的导入和纯Python函数:

<%!
    import mylib
    import re

    def filter(text):
        return re.sub(r‘^@‘, ‘‘, text)
%>

可以在模板中的任何位置声明任意数量的 <%! %> 块。它们将按出现的顺序生成为一个单独的模块代码块,放在所有渲染调用之前。

标签

Mako提供的其他东西以标签的形式出现。所有标签使用相同的语法,和XML标签类似,但是在标签名之前加上了 %字符。标签结束方式和XML类似:

<%include file="foo.txt"/>

<%def name="foo" buffered="True">
    this is a def
</%def>

每个标签都有一组属性。有些属性是必需的。很多属性支持运算,这意味着你可以在属性文本中嵌入一个表达式(使用 ${} ):

<%include file="/foo/bar/${myfile}.txt"/>

属性是否支持运行时运算取决于标签的类型和它编译到模板的方式。想知道能否添加表达式的最好方法就是试一下!词法分析器会告诉你是否有效。

下面是全部的标签的一个快速总结:

<%page>

该标签定义了模板的一些通用特性,包括缓存参数和模板调用的参数的可选列表。

<%page args="x, y, z=‘default‘"/>

也可以定义缓存特性:

<%page cached="True" cache_type="memory"/>

目前每个模板只有一个 <%page> 标签生效,其他的会被忽略。以后的版本中这会被改进,但是现在请确保你的模板中只用了一个 <%page> 标签,否则可能得不到你想要的结果。 <%page> 的用途参考 The body() Method 和 Caching 。

<%include>

这是和其他模板语言类似的一个标签, %include 接受一个文件参数,调用那个文件的渲染结果:

<%include file="header.html"/>

    hello world

<%include file="footer.html"/>

它还接受 <%page> 标签的参数,应用到导入的模板上:

<%include file="toolbar.html" args="current_section=‘members‘, username=‘ed‘"/>

<%def>

%def 标签定义一个Python函数,函数可以在模板的其他位置调用。基本的思想很简单:

<%def name="myfunc(x)">
    this is myfunc, x is ${x}
</%def>

${myfunc(7)}

%def 标签比Python的 def 强大得多,因为Mako提供了很多额外的功能,比如能够将函数作为模板的“方法”,自动传递当前的 Context ,使用缓冲/过滤/缓存标志,作为参数传递给其他的函数调用。 %def 的全部细节见 Defs and Blocks 。

<%block>

<%block> 标签和 %def 类似,但它会在根作用域立即执行,而且可以是匿名的:

<%block filter="h">
    some <html> stuff.
</%block>

借鉴了Jinja2的块,有名字的块实现了一种很方便的继承方法:

<html>
    <body>
    <%block name="header">
        <h2><%block name="title"/></h2>
    </%block>
    ${self.body()}
    </body>
</html>

块在 Using Blocks 中有介绍,还有 Inheritance 。

<%namespace>

Mako中的 %namespace 和Python的 import 语句等价。通过它可以访问其他模板的所有的渲染函数和metadata,Python模块,还有本地定义的函数“包”。

<%namespace file="functions.html" import="*"/>

%namespace 生成的底层对象是一个 mako.runtime.Namespace 实例。它是模板中的一个核心结构,用来引用模板的特定信息,比如当前的URI、继承结构和其他一些东西。名字空间见 Namespaces 。

<%inherit>

通过继承可以实现模板的继承链。它和其他模板语言的概念类似。

<%inherit file="base.html"/>

当使用 %inherit 标签时,控制首先被传递到继承模板的顶层模板,由它来决定如何处理调用部分。Mako在这部分实现的非常灵活,包括动态继承、内容封装、多态方法调用。参考 Inheritance 。

<%nsname:defname>

可以通过 <%<namespacename>:<defname>> 来在一个名字空间中自定义一个标签。它的单标签和双标签形式分别对应行内表达式和 <%call> 标签。

<%mynamespace:somedef param="some value">
    this is the body
</%mynamespace:somedef>

如何创建自定义标签,参考 Calling a Def with Embedded Content and/or Other Defs 。

<%call>

%call 标签是用户定义标签的传统形式,大致和上面的 <%namespacename:defname> 等价。该标签也参考 Calling a Def with Embedded Content and/or Other Defs 。

<%doc>

%doc 标签处理多行注释:

<%doc>
    these are comments
    more comments
</%doc>

<%text>

该标签使Mako词法分析器跳过该部分的处理,返回整个内容。主要用于写Mako的文档:

<%text filter="h">
    heres some fake mako ${syntax}
    <%def name="x()">${x}</%def>
</%text>

从模板中提前返回

有时你想在模板或 <%def> 方法的中间停止处理,只用当前得到的结果。可以在Python代码块中使用 return 语句来实现。

% if not len(records):
    No records found.
    <% return %>
% endif

或:

<%
    if not len(records):
        return
%>
时间: 2024-10-09 19:09:48

模板库Mako的语法的相关文章

Python模板库Mako的用法

Mako是一个高性能的Python模板库,它的语法和API借鉴了很多其他的模板库,如Django.Jinja2等等. 基本用法 创建模板并渲染它的最基本的方法是使用 Template 类: from mako.template import Template t = Template('hello world!') print t.render() 传给 Template 的文本参数被编译为一个Python模块.模块包含一个 render_body() 函数,它产生模板的输出.调用 render

标准模板库(STL)学习探究之vector容器

标准模板库(STL)学习探究之vector容器  C++ Vectors vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据.为了可以使用vector,必须在你的头文件中包含下面的代码:#include <vector>构造函数. Vectors 包含着一系列连续存储的元素,其行为和数组类

C++标准模板库学习。。。

作为C++标准库相当重要的一部分,STL库提供一系列组件操作.它主要可以分为容器.迭代器.基本算法.函数对象以及内存分配器和配接器六个部分.整个STL库的代码都采用模板函数以及模板类的方式实现,具有高度的通用性.对于传统的应用程序来讲,模板库支持并且倡导一种新的编程风格,即称为泛型编程思想,以通用的模板方式来编写应用程序中的数据结构与算法. 16.1  STL常见容器 C++标准STL库中封装实现了常见数据结构,并以容器的方式提供给用户使用.STL容器主要包含vector向量.deque队列.l

C++ primer plus读书笔记——第16章 string类和标准模板库

第16章 string类和标准模板库 1. string容易被忽略的构造函数: string(size_type n, char c)长度为n,每个字母都为c string(const string & str, size_type pos = 0, size_type n = pos)初始化为str中从pos开始到结尾的字符,或从pos开始的n个字符 string(const char *s, size_type n)初始化为s指向的前n个字符,即使超过了s的结尾: string(Iter b

【超精简JS模版库/前端模板库】原理简析 和 XSS防范

使用jsp.php.asp或者后来的struts等等的朋友,不一定知道什么是模版,但一定很清楚这样的开发方式: <div class="m-carousel"> <div class="m-carousel-wrap" id="bannerContainer"> </div> </div> <ul class="catelist onepx" onepxset="

C++标准模板库集合类与映射类总结

一.STL集合类 标准模板库向程序员提供了一些容器类,以便在应用程序中频繁而快速的搜索.std::set和std::multiset用于存储一组经过排序的元素,其查找元素的复杂度为对数,而unordered集合的插入和查找时间是固定的. 容器set和multiset快速查找键,键是存储在一维容器中的值,multiset可存储重复的键值,而set不行.STL容器是泛型模板类,可用于存储字符串.整型.结构或对象. 为了实现快速搜索,STL set和multiset内部结构类似二叉树,将元素插入到se

C++标准模板库Stand Template Library(STL)简介与STL string类

参考<21天学通C++>第15和16章节,在对宏和模板学习之后,开启对C++实现的标准模板类STL进行简介,同时介绍简单的string类.虽然前面对于vector.deque.list等进行过学习和总结,但并没有一个宏观上的把握,现在通过上一篇和这一篇博文,将对C++模板以及基于C++模板的STL关联起来,形成一个总体的把握,对于掌握C++中模板(template)这一强有力的工具会十分有帮助.本文的主要内容有: (1) STL容器: (2) STL迭代器: (3) STL算法: (4) ST

通过例子进阶学习C++(七)CMake项目通过模板库实现约瑟夫环

本文是通过例子学习C++的第七篇,通过这个例子可以快速入门c++相关的语法. 1.问题描述 回顾一下约瑟夫环问题:n 个人围坐在一个圆桌周围,现在从第 s 个人开始报数,数到第 m 个人,让他出局:然后从出局的下一个人重新开始报数,数到第 m 个人,再让他出局......,如此反复直到所有人全部出局为止. 上一篇我们通过数组.静态链表实现了约瑟夫环,具体参考: 通过例子进阶学习C++(六)你真的能写出约瑟夫环么 本文,我们进一步深入分析约瑟夫环问题,并通过c++模板库实现该问题求解,最后我们说明

标准模板库

-------------------siwuxie095 在长期的编码中,聪明的程序员们发现:有一些代码经常碰到, 而且需求特别稳定,于是,各大公司在出售自己的 IDE 环境时, 就会把这些模板代码打包,一起销售 慢慢地,这些大公司之间就达成了某种共识,觉得应该把这些 涉及模板的通用代码进一步的统一和规范,于是,大家慢慢形 成了一套 C++ 的标准模板,就是现在所看到的标准模板库 标准模板库 标准模板库,即 Standard Template Lib,简称为 STL 标准模板库所涉及的内容非常