edx抛弃了django自身的模板,选择使用mako。
##关于mako
Mako is a template library written in Python. Mako’s syntax and API borrows from the best ideas of many others, including Django and Jinja2 templates, Cheetah, Myghty, and Genshi
##mako设计哲学
Python is a great scripting language. Don’t reinvent the wheel…your templates can handle it !
##中文文档(摘自这儿)
####表达式替换
1
2
3
4
|
:::text
from mako.template import Template
t = Template('hello, ${name}!')
print t.render(name='yeolar')
|
${} 标签中的内容由Python直接计算,因此也可以使用完整的表达式:
####表达式转义
1
2
|
:::text
${"this is some text" | u}
|
u 表示URL转义, h 表示HTML转义, x 表示XML转义, trim 为空白截断函数。
更多有关内建的过滤函数,包括如何编写自己的过滤函数,见Filtering and Buffering
####控制结构
1
2
3
4
5
6
7
8
9
10
|
:::text
% 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
|
控制结构写成 % 标记后面跟正常的Python控制表达式
% 可以放在前面没有文本的行的任何地方,并且缩进是不敏感的。Python所有的“冒号”表达式都可以使用,包括 if/elif/else 、 while 、 for ,甚至是 def ,不过对 def Mako有更好的内建标签。
####循环上下文
1
2
3
4
|
:::text
% for a in ("one", "two", "three"):
<li>Item ${loop.index}: ${a}</li>
% endfor
|
####注释
有两种形式的注释。单行注释在行首使用 ##
多行注释通过
<%doc></%doc>
####Python代码块
可以用 <% %> 标签引入任意Python代码块
1
2
3
4
5
6
7
8
|
:::text
<%
x = db.get_resource('foo')
y = [z.element for z in x if x.frobnizzle==5]
%>
% for elem in y:
element: ${elem}
% endfor
|
<% %> 里面,可以写普通的Python代码块。代码的整体缩进不受限制
####模块级的块
用 <%! %> 表示
1
2
3
4
5
6
7
8
|
:::text
<%!
import mylib
import re
def filter(text):
return re.sub(r'^@', '', text)
%>
|
代码不能访问模板的上下文
放在所有渲染调用之前。
####标签
Mako提供的其他东西以标签的形式出现。所有标签使用相同的语法,和XML标签类似,但是在标签名之前加上了 % 字符。标签结束方式和XML类似:
1
2
3
4
5
6
|
:::text
<%include file="foo.txt"/>
<%def name="foo" buffered="True">
this is a def
</%def>
|
- <%page> :该标签定义了模板的一些通用特性,包括缓存参数和模板调用的参数的可选列表。
- <%include>:%include 接受一个文件参数,调用那个文件的渲染结果
- <%def>:%def 标签定义一个Python函数,函数可以在模板的其他位置调用。
- <%block>:借鉴了Jinja2的块,有名字的块实现了一种很方便的继承方法
- <%namespace>:和Python的 import 语句等价
- <%inherit>:通过继承可以实现模板的继承链。它和其他模板语言的概念类似。
- <% return %>:有时你想在模板或 <%def> 方法的中间停止处理,只用当前得到的结果
##一些笔记
####namespace
Namespaces are used to organize groups of defs into categories, and also to “import” defs from other files.
很像python中的模块。类比模块的思路可以很快理解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
:::text
## components.html
<%def name="comp1()">
this is comp1
</%def>
<%def name="comp2(x)">
this is comp2, x is ${x}
</%def>
## index.html
<%namespace name="comp" file="components.html"/>
Here's comp1: ${comp.comp1()}
Here's comp2: ${comp.comp2(x=5)}
##可以包含import属性
<%namespace file="components.html" import="comp1, comp2"/>
Heres comp1: ${comp1()}
Heres comp2: ${comp2(x=5)}
|
####Defs and Blocks
<%def> provides a construct that is very much like a named Python def, the <%block> is more layout oriented.
named blocks can be referred to by an inheriting template.
1
2
3
4
5
6
|
:::text
<%def name="hello()">
hello world
</%def>
the def: ${hello()}
|
####inheritance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
:::text
## index.html
<%inherit file="base.html"/>
<%block name="header">
this is some header content
</%block>
this is the body content.
## base.html
<html>
<body>
<div class="header">
<%block name="header"/>
</div>
${self.body()}
<div class="footer">
<%block name="footer">
this is the footer
</%block>
</div>
</body>
</html>
##output
<html>
<body>
<div class="header">
this is some header content
</div>
this is the body content.
<div class="footer">
this is the footer
</div>
</body>
</html>
|
defs和block的区别
The def simply doesn’t call itself automatically。
以下两者等效
1
2
3
4
5
6
|
:::text
##def
<%def name="header()"></%def>${self.header()}
##block
<%block name="header()"></%block>
|
###参考教程