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>

###参考教程