使用预渲染事件公开 h Helper 对象

Pylons 1.x暴露了一个常规命名的模块 helpers.py 作为 h 对象位于其呈现的每个mako/genshi/jinja2模板的顶级命名空间中。您可以使用 BeforeRender 事件订阅服务器。

First, create a module named helpers.py in your Pyramid package at the top level (next to __init__.py )我们将导入python标准库 string 稍后在模板中使用的模块:

# helpers.py

import string

在主管道顶部 __init__ Pyramid 应用程序包的模块,导入新的 helpers 您创建的模块以及 BeforeRender 事件类型。在导入下面创建一个函数,该函数将作为事件订阅服务器:

1
2
3
4
5
6
7
# __init__.py

from pyramid.events import BeforeRender
from myapp import helpers

def add_renderer_globals(event):
    event['h'] = helpers

main 功能相同 __init__ ,连接订阅服务器,以便在 BeforeRender 事件已发出::

1
2
3
4
5
def main(global_settings, **settings):
    config = Configurator(....) # existing code
    # .. existing config statements ... #
    config.add_subscriber(add_renderer_globals, BeforeRender)
    # .. other existing config statements and eventual config.make_app()

At this point, with in any view that uses any templating system as a Pyramid renderer, you will have an omnipresent h 顶级名称,它是对 helpers 您创建的模块。例如,如果您有这样的视图:

@view_config(renderer='foo.pt')
def aview(request):
    return {}

foo.pt Chameleon 模板,您可以这样做:

1
 ${h.string.uppercase}

作为此语句的结果插入到模板中的值将为 ABCDEFGHIJKLMNOPQRSTUVWXYZ (至少如果你使用的是英语系统)。

可以向添加更多导入和函数 helpers.py 使模板中的功能可用。

使用BeforeRender事件公开Mako base 模板

如果要更改模板,请使用 %inherit 根据用户是否登录,您可以执行以下操作:

@subscriber(BeforeRender)
def add_base_template(event):
    request = event.get('request')
    if request.user:
        base = 'myapp:templates/logged_in_layout.mako'
        event.update({'base': base})
    else:
        base = 'myapp:templates/layout.mako'
        event.update({'base': base})

然后在您的mako文件中,您可以调用%inherit,如下所示:

<%inherit file="${context['base']}" />

must 以这种方式调用变量是因为Mako的工作方式。除了 context 直到之后 %inherit 被称为。意识到 context 这里不是遍历意义上的 Pyramid 上下文(存储在 request.context ) but rather the Mako rendering context.

使用BeforeRender事件公开 Chameleon base 模板

To avoid defining the same basic things in each template in your application, you can define one base 模板,并从其他模板中继承。

注解

Pyramid 示例应用程序- shootout 使用这种方法。

首先,在 Pyramid 项目的“初始”中添加订户:

config.add_subscriber('YOURPROJECT.subscribers.add_base_template',
                      'pyramid.events.BeforeRender')

然后添加 subscribers.py 项目目录中的模块:

1
2
3
4
5
from pyramid.renderers import get_renderer

def add_base_template(event):
    base = get_renderer('templates/base.pt').implementation()
    event.update({'base': base})

完成此操作后,您可以使用 base template to extend other templates. For example, the base 模板如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      metal:define-macro="base">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <title>My page</title>
    </head>
    <body>
        <tal:block metal:define-slot="content">
        </tal:block>
    </body>
</html>

每个模板使用 base 模板将如下所示:

1
2
3
4
5
6
7
8
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      metal:use-macro="base.macros['base']">
    <tal:block metal:fill-slot="content">
        My awesome content.
    </tal:block>
</html>

这个 metal:use-macro="base.macros['base']" 这里的陈述很重要。内部内容 <tal:block metal:fill-slot="content"></tal:block> 标记将替换中的相应块 base 模板。You can define as many slots in as you want. For more information please see Macro Expansion Template Attribute Language 文档。

将构建基块与 Chameleon 一起使用

如果你理解 base template chapter, using building blocks is very simple and straight forward. 在 subscribers.py 模块扩展 add_base_template 功能如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from pyramid.events import subscriber
from pyramid.events import BeforeRender
from pyramid.renderers import get_renderer

@subscriber(BeforeRender)
def add_base_template(event):
    base = get_renderer('templates/base.pt').implementation()
    blocks = get_renderer('templates/blocks.pt').implementation()
    event.update({'base': base,
                  'blocks': blocks,
                  })

使 Pyramid 扫描模块,以便找到 BeforeRender 事件:

1
2
3
4
5
def main(global_settings, **settings):
    config = Configurator(....) # existing code
    # .. existing config statements ... #
    config.scan('subscriber')
    # .. other existing config statements and eventual config.make_app()

Now, define your building blocks in templates/blocks.pt . 例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal">
  <tal:block metal:define-macro="base-paragraph">
    <p class="foo bar">
      <tal:block metal:define-slot="body">
      </tal:block>
    </p>
  </tal:block>

  <tal:block metal:define-macro="bold-paragraph"
             metal:extend-macro="macros['base-paragraph']">
    <tal:block metal:fill-slot="body">
      <b class="strong-class">
        <tal:block metal:define-slot="body"></tal:block>
      </b>
    </tal:block>
  </tal:block>
</html>

您现在可以使用如下构建基块:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      metal:use-macro="base.macros['base']">
  <tal:block metal:fill-slot="content">
    <tal:block metal:use-macro="blocks.macros['base-paragraph']">
      <tal:block metal:fill-slot="body">
        My awesome paragraph.
      </tal:block>
    </tal:block>

    <tal:block metal:use-macro="blocks.macros['bold-paragraph']">
      <tal:block metal:fill-slot="body">
        My awesome paragraph in bold.
      </tal:block>
    </tal:block>

  </tal:block>
</html>

致使 None 作为mako模板中的空字符串

For the following Mako template:

<p>${nunn}</p>

By default, Pyramid will render:

<p>None</p>

有些人更喜欢价值观 None 在Mako模板中呈现为空字符串。换言之,他们希望输出是:

<p></p>

在 Pyramid 配置文件中使用以下设置以获得此行为:

[app:myapp]
mako.imports = from markupsafe import escape_silent
mako.default_filters = escape_silent