语法

文档的某些部分直接复制自 Slim 官方文档

行内标识符(Line Indicator)

|

管道符告诉 Plim 只需要复制整行即可,不需要做任何转换。

,

逗号告诉 Plim 复制整行(与管道符类似),但是在行尾添加一个空格字符。

注解

在 Slim 中对应的是单引号(')。

-

横线表示控制模块,包括循环、条件、mako 标签以及扩展。

=

等号表示 Python 调用,并会将代码的输出添加到 HTML 输出缓冲区中。

=,

与等号类似,但是会在 Python 代码的输出后添加一个空格字符。

==

与等号类似,但是会在输出为 mako 时添加 ‘过滤器 “n” <http://docs.makotemplates.org/en/latest/filtering.html>`_ 。

== python_expression                       =>      ${python_expression|n}

== python_expression | custom_filter       =>      ${python_expression |n,custom_filter}
==,

== 类似,但是会在 Python 表达式的结尾添加空格字符。

/

正斜线用于代码注释,其后的任何内容都不会输出到 Mako 模板中。

注解

Slim 中的 “/!” HTML 注释并没有对应的 Plim 写法 ,这是因为 Plim 现在已经支持原生的 HTML 标记,无需多余的控制语法。

/ You can use raw HTML comment tags, as well as all other tags
<!-- HTML comment -->
<div>

  / You can use Plim markup inside the raw HTML
  a href="#" = link.title

/ If you use raw HTML, you have to close all tags manually
</div>

缩进

Plim 缩进规则和 Slim 类似:缩进很重要,但是并不需要像 Haml 那样严格,你尽可以在代码中使用 2 空格、5 空格缩进。实际上只需要提供 1 个以上的空格即符合 Plim 的语法。

标签属性

静态属性

Static tag attributes can be specified in the same form as any valid python string declaration.

例如:

input type='text' name="username" value='''Max Power''' maxlength="""32"""

将会输出:

<input type="text" name="username" value="Max Power" maxlength="32"/>

和 Python 字符串声明一样,你需要注意引号的转译:

input value='It\'s simple'
input value="It's simple"
input value='''It's simple'''
input value="""It's simple"""

input value="He said \"All right!\""
input value='He said "All right!"'
input value='''He said "All right!"'''
input value="""He said "All right!\""""

对于纯数字属性,引号并不是必须的:

input type='text' name="measure" value=+.97 maxlength=32

输出:

<input type="text" name="measure" value="+.97" maxlength="32"/>

动态属性

动态值必须以以下形式传入:

  • Mako 表达式

    input type="text" name="username" value="${user.name}" maxlength=32
    a href="${request.route_url('user_profile', tagname=user.login, _scheme='https')}"
    

    或者

    input type="text" name="username" value=${user.name} maxlength=32
    a href=${request.route_url('user_profile', tagname=user.login, _scheme='https')}
    
  • Python 表达式

    input type="text" name="username" value=user.name maxlength=32
    a href=request.route_url('user_profile', tagname=user.login, _scheme='https')
    

    或者使用圆括号

    input type="text" name="username" value=(user.name) maxlength=32
    a href=(request.route_url('user_profile', tagname=user.login, _scheme='https'))
    

以上代码都会输出相同的 Mako 代码:

<input type="text" name="username" value="${user.name}" maxlength="32"/>
<a href="${request.route_url('user_profile', tagname=user.login, _scheme='https')}"></a>

布尔属性

布尔属性即可以通过静态也可以使用动态方法定义:

静态属性示例:

/ Static boolean attribute "disabled"
input type="text" name="username" disabled="disabled"

/ If you wrap your attributes with parentheses, you can use
  shortcut form
input (type="text" name="username" disabled)

动态属性示例(注意结尾的问号):

/ Dynamic boolean attribute "disabled"
  will be evaluated to 'disabled="disabled"' if `is_disabled`
  evaluates to True

input type="text" name="username" disabled=${is_disabled}?

/ or you can write it that way
input type="text" name="username" disabled=is_disabled?

/ or even that way
input type="text" name="username" disabled=(is_disabled or
                                            is_really_disabled)?

Dynamic unpacking

这个功能和 Slim 的 splat 属性 对应,但是语法上稍有不同,以契合 Python 的 **kwargs 语法。

假设有这样一个 Python 字典:

attrs = {
    'id': 'navbar-1',
    'class': 'navbar',
    'href': '#',
    'data-context': 'same-frame',
}

Now we can unpack the dictionary in order to populate tags with attributes. The following line:

a**attrs Link

将会输出与下面这段 HTML 等价的 Mako 代码:

<a id="navbar-1" class="navbar" href="#" data-context="same-frame">Link</a>

其它示例:

a **attrs|Link

a **attrs **more_attrs Link

a(**attrs disabled) Disabled Link

a **function_returning_dict(
  *args, **kwargs
) Link

Attribute Wrapping

你可以是用圆括号 () 包裹标签属性。但和 Slim 不同的是,Plim 并不支持方括号 [] 和花括号 {} 用作属性封装。

body
  h1(id="logo" class="small tagline") = page_logo
  h2 id=(id_from_variable + '-idx') = page_tagline

使用属性包裹后,属性赋值将支持跨行:

body

  h1 (id="logo"
    class="small tagline") = page_logo

  h2 id=(
    id_from_variable +
    '-idx'
  ) = page_tagline

单行标签内容

你可以将标签中的内容与标签写在同一行:

body
  h1 id="headline" Welcome to my site.

也可以使用缩进嵌套。注意:需要使用管道符或者 隐式文本标识(Implicit literal indicators)

body
  h1 id="headline"

    / Explicit literal with pipe character
    | Welcome to my site.

    / Implicit literal (uppercase letter at the beginning of the line)
    Yes, Welcome to my site

动态标签内容

你可以在同一行调用动态属性

body
  h1 id="headline" = page_headline

或者缩进:

body
  h1 id="headline"
    = page_headline

idclass 的简易写法

你可以使用下面的格式设置标签的 id 和 class 属性:

body

  / Static shortcuts
  h1#headline
    = page_headline
  h2#tagline.small.tagline
    = page_tagline
  .content
    = show_content

与下面的写法等价:

body
  h1 id="headline"
    = page_headline
  h2 id="tagline" class="small tagline"
    = page_tagline
  div class="content"
    = show_content

与 Slim 不同 的是,Plim 支持在这种简写中混合动态表达式:

/ Dynamic shortcuts
h1#headline-${'dynamic'} = page_headline
h2#${tagline.id}.small-${tagline.cls}.${tagline.other_cls}
  = page_tagline
.${'content'}
  = show_content

与下面的写法等价:

h1 id="headline-${'dynamic'}" = page_headline
h2 id="${tagline.id}" class="small-${tagline.cls} ${tagline.other_cls}"
  = page_tagline
div class="${'content'}"
  = show_content

行内标签

你可能会希望这样更简洁的行内标签支持:

ul
  li.first: a href="/a" A link
  li: a href="/b" B link

别忘了,还可以使用圆括号增加代码的可读性:

ul
  li.first: a(href="/a") A link
  li: a(href="/b") B link

行内状态(Inline Statement)

Python 循环和条件表达式的单行写法和 HTML 标签类似:

ul: -for link in ['About', 'Blog', 'Sitemap']: li: a href=route_to(link) = link

将会输出:

<ul>
%for link in ['About', 'Blog', 'Sitemap']:
<li><a href="${route_to(link)}">${link}</a></li>
%endfor
</ul>

Python 代码与纯文本混合

使用标准 Mako 表达式语法 。文本的解析方式决定于 Mako 默认过滤器的设置

body
  h1 Welcome ${current_user.name} to the show.
  Explicit non-escaped ${content|n} is also possible.

目前,Mako 并没有提供一种简单的其嵌入表达式的渲染方法(比如原样输出)。你可以使用 <%text> 标签(或者 Plim -text 标记)或者下面的取巧办法:

body
  h1 Welcome ${'${current_user.name}'} to the show.

嵌入的标记

你可以在隐式文本块中嵌入 Plim 标记:

a href="#" Embedded `strong string` everywhere

将输出:

<a href="#">Embedded <strong>string</strong> everywhere</a>

如果你想要紧接着使用两个嵌入标记,需要在第一个嵌入标记后跟上一个下划线 _

a href="#" Embedded `strong string`_`i s` everywhere

将输出:

<a href="#">Embedded <strong>string</strong><i>s</i> everywhere</a>

这种嵌入机制可迭代,也就是说你可以在嵌入标记中使用嵌入标记:

Another `a href="#" very ``strong funny ````i recursive``````` test

将输出:

Another <a href="#">very <strong>funny <i>recursive</i></strong></a> test

停用 HTML 转义

使用双等号:

body
  h1 id="headline"
    == page_headline

或者在表达式的结尾添加 | n 过滤器:

body
  h1 id="headline"
    = page_headline | n

代码注释

使用正斜线 / 标记代码中的注释:

body
  p
    / This is a comment.
      Indentation is the natural way to get block comments

原生 HTML 标签

在 Plim 中你可以使用原生的 HTML 标签,也可以和所有逻辑控制模块混合使用,在下面的情况中非常实用:

- if edit_profile
  / Wrap interface with editable block
  <div id="edit-profile">

- include new_or_edit_interface.html

- if edit_profile
  / close wrapper tag
  </div>

Doctype 声明

Plim 并不提供默认的 doctype 声明,因此你需要指定 HTML 的 doctype

doctype 5

可用的 HTML doctype 包括:

doctype html

<!DOCTYPE html>

doctype 5

<!DOCTYPE html>

doctype 1.1

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

doctype strict

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

doctype xml

<?xml version="1.0" encoding="utf-8" ?>

doctype transitional

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

doctype frameset

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

doctype basic

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">

doctype mobile

<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">

逻辑控制

if/elif/else

-if items
  table
    -for item in items
      tr
        td = item.name
        td = item.price
-elif show_empty
  p No items found
-else
  a href=request.route_url('items.add') =, _('Add items')

unless

unless- if not (<EXPR>) 的缩写形式

-unless user.authenticated
  p Please, sign in.
-else
  p Welcome, ${user.name}!

for 循环

table
  -for item in items
    tr
      td = item.name
      td = item.price

你可以在 -for 中使用 -continue-break 标记。参考链接 Returning Early from a Template.

while statement

-python
  i = 0
  limit = 5

ul
  -while i < limit
    li#idx-${i}.up: a href='#' title="Title" == i
    -py i += 1

你同样可以在 -while 循环中使用 -continue-break 标记。参考链接 Returning Early from a Template.

until

until- while not (<EXPR>) 的简写方式:

-until i < 0
  li#idx-${i}.down-${i}: a href='''#''' title="""Title""" ==, i
  -py i -= 1

你同样可以在 -until 中使用 -continue-break 标记参考链接 Returning Early from a Template

with

Mako 0.7.0 中引入了``% with`` 标记:

-with <EXPR> as <VAR>
  / Do some stuff

try/except

- try
  div = item[0]
  div = price['usd']

- except IndexError
  div IndexError

- except KeyError as e
  div = e

Returning Early from a Template

Plim 同样提供 Mako <% return %> 标签 的简写形式:

- if not len(records)
  No records found.
  -return

等价于:

- if not len(records)
  No records found.
  -py return

你可以在 Plim 模板中的任意位置这样使用,而不独是控制结构中。

There are also the -break and -continue shortcuts, that can be used inside the -for, -while, and -until loops.

文本块

你可以定义显式或者隐式的文本块,区别在于以 | 显式声明符还是隐式声明符开头。

显式声明

使用管道符 ( | ) 或者逗号 ( , ) literal indicators to start the escape.Each following line that is indented greater than the first one is copied over.

body
  p
    / Explicit literal
    | This is a test of the text block.
body
  p
    |
      This is a test of the text block.

上面的输出结果如下:

<body><p>This is a test of the text block.</p></body>

边缘空格将被抹去。其它位置的空格则会原样复制。

body
  p
    |  This line is on the zero left margin.
        This line will have one space in front of it.
          This line will have two spaces in front of it.
            And so on...

隐式文本块

以下字符开头的文本块将被当作隐式声明:

  • 大写 ASCII 字母;

  • 任何非 ASCII 字符;

  • 没有正/负号的数字;

  • HTML 转义字符,如 &nbsp;

  • Mako 格式的开括号 ${

  • an open square brace [;
  • an open parenthesis (;
  • any unicode character outside the range of U0021 - U007E (ASCII 33 - 126).
p
  | pipe is the explicit literal indicator. It is required if your line starts with
    the non-literal character.

p
  I'm the implicit literal, because my first letter is in uppercase.

p
  1. Digits
  2. are
  3. the
  4. implicit
  5. literals
  6. too.

p
  ${raw_mako_expression} indicates the implicit literal line.

p
  If subsequent lines do not start with implicit literal indicator,
    you must indent them
  | or you can use the "explicit" pipe.
p
  если ваш блок текста написан на русском, или любом другом языке, не
  использующим символы из ASCII-диапазона, то вам даже не обязательно
  использовать заглавную букву в начале блока.

  / if your literal blocks are written in Russian, or any other
    language which uses non-ASCII letters, you can put even the
    lowercase letter at the beginning of the block

Python 代码块

旧式写法

使用 -py 或者 -python 标记来代替 <% %> mako 标签

例如:

- python x = 1

或者

-py
    x = 1

或者:

- python x = 1
    y = x + 1
    if True:
        y += 1
    else:
        y -= 1

在后面的例子中, x = 1 将会和 y = x + 1 出现在同一行。

新式写法

0.9.1 新版功能: 新式写法将提高嵌入的 Python 代码的可读性。

新式写法使用三个以上的横线开头的字符串作为 Python 代码块的开始。

下面是对应的新式写法示例:

--- x = 1
-------------
    x = 1
--- x = 1
    y = x + 1
    if True:
        y += 1
    else:
        y -= 1

And here’s an example of how we can use an inline statement for providing a block description

ul#userlist
    ---------- # prepare a list of users ---------------
        users = UsersService.get_many(max=100, offset=0)
        friends = UsersService.get_friends_for(users)
    ----------------------------------------------------
    -for user in users: li
        h4: a#user-${user.id} href='#' = user.name
        ul: -for friend in friends[user.id]: li
            a#friend-${friend.id} href='#' = friend.name

输出(真实输出不包括下面的缩进):

<ul id="userlist">
    <%
        # prepare a list of users
        users = UsersService.get_many(max=100, offset=0)
        friends = UsersService.get_friends_for(users)
    %>

    %for user in users:
        <li>
            <h4>
                <a href="#" id="user-${user.id}">${user.name}</a>
            </h4>
            <ul>
                %for friend in friends[user.id]:
                    <li>
                        <a href="#" id="friend-${friend.id}">${friend.name}</a>
                    </li>
                %endfor
            </ul>
        </li>
    %endfor
</ul>

模块级 Block

使用 -py! 或者 -python! 代替 <%! %> mako 标签

-py!
    import mylib
    import re

    def filter(text):
        return re.sub(r'^@', '', text)

0.9.1 新版功能: 新式写法:

---! import mylib
     import re

     def filter(text):
         return re.sub(r'^@', '', text)

Mako 标签

Plim supports a complete set of Mako Tags, except the <%doc>. The latter has been considered deprecated, since Plim itself has built-in support of multi-line comments.

注解

Plim 支持 <%doc> 以外的大部分 Mako 标签 ,Plim 本身提供了多行注释的另一种写法,因此这一标记略显多余。

-page 标签

-page args="x, y, z='default'"

输出:

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

See the details of what <%page> is used for in The body() Method and Caching sections of Mako Documentation.

-include 标签

-include footer.html

或者

-include file="footer.html"

输出是一样的:

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

查看 <%include> 章节 或者其它文档以获取更多内容。

-inherit 标签

-inherit base.html

或者

-inherit file="base.html"

同样输出:

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

参考 Mako 继承章节 获取更多信息。

-namespace 标签

-namespace name="helper" helpers.html

或者

-namespace file="helpers.html" name="helper"

输出:

<%namespace file="helpers.html" name="helper"/>

更多信息参见 Mako 文档 namespace 章节

-def 标签

-def account(accountname, type='regular')

或者

-def name="account(accountname, type='regular')"

输出:

<%def name="account(accountname, type='regular')">
</%def>

See Mako’s defs and blocks documentation to get more information about functions and blocks.

-block 标签

-def 不同的是,block 支持匿名:

-block
  This is an anonymous block.

当然也可以用于定义命名函数:

-block name="post_prose"
  = pageargs['post'].content

或者

-block post_prose
  = pageargs['post'].content

以上 Plim 片段都会输出相同的 Mako 标记:

<%block name="post_prose">
${pageargs['post'].content}</%block>

You can also specify other block arguments as well

- block filter="h"
  html this is some escaped html.

See Mako’s defs and blocks documentation to get more information about functions and blocks.

-call 标签

-call 可以用于定制标签。

下面的例子

-call expression="${4==4}" self:conditional
  |i'm the result

- call expression=${4==4} self:conditional
  | i'm the result

- call self:conditional
  | i'm the result

- call self:conditional

将输出:

<%self:conditional expression="${4==4}">
i'm the result
</%self:conditional>

<%self:conditional expression="${4==4}">
i'm the result
</%self:conditional>

<%self:conditional>
i'm the result
</%self:conditional>

<%self:conditional>
</%self:conditional>

更多信息参见 Mako 文档 <%nsname:defname> 章节Calling a Def with Embedded Content and/or Other Defs 章节。

-text 标签

和 Mako 类似 ,该标签中的代码将不会对 Mako 命令进行任何渲染操作,这在写 Mako 文档这样的情况下会很有帮助:

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

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

- text filter="h" = syntax
  <%def name="x()">${x}</%def>

-text
  here's some fake mako ${syntax}
  <%def name="x()">${x}</%def>

-text , here's some fake mako ${syntax}
  <%def name="x()">${x}</%def>