UI 模块
Tornado 支持一些 UI 模块,它们可以帮你创建标准的,易被重用的应用程序级的 UI 组件。 这些 UI 模块就跟特殊的函数调用一样,可以用来渲染页面组件,而这些组件可以有自己的 CSS 和 JavaScript。
例如你正在写一个博客的应用,你希望在首页和单篇文章的页面都显示文章列表,你可以创建 一个叫做 Entry
的 UI 模块,让他在两个地方分别显示出来。首选需要为你的 UI 模块 创建一个 Python 模组文件,就叫 uimodules.py
好了:
class Entry(tornado.web.UIModule):
def render(self, entry, show_comments=False):
return self.render_string(
"module-entry.html", entry=entry, show_comments=show_comments)
然后通过 ui_modules
配置项告诉 Tornado 在应用当中使用 uimodules.py
:
class HomeHandler(tornado.web.RequestHandler):
def get(self):
entries = self.db.query("SELECT * FROM entries ORDER BY date DESC")
self.render("home.html", entries=entries)
class EntryHandler(tornado.web.RequestHandler):
def get(self, entry_id):
entry = self.db.get("SELECT * FROM entries WHERE id = %s", entry_id)
if not entry: raise tornado.web.HTTPError(404)
self.render("entry.html", entry=entry)
settings = {
"ui_modules": uimodules,
}
application = tornado.web.Application([
(r"/", HomeHandler),
(r"/entry/([0-9]+)", EntryHandler),
], **settings)
在 home.html
中,你不需要写繁复的 HTML 代码,只要引用 Entry
就可以了:
{% for entry in entries %}
{% module Entry(entry) %}
{% end %}
在 entry.html
里面,你需要使用 show_comments
参数来引用 Entry
模块,用来 显示展开的 Entry
内容:
{% module Entry(entry, show_comments=True) %}
你可以为 UI 模型配置自己的 CSS 和 JavaScript ,只要复写 embedded_css
、 embedded_javascript
、javascipt_files
、css_files
就可以了:
class Entry(tornado.web.UIModule):
def embedded_css(self):
return ".entry { margin-bottom: 1em; }"
def render(self, entry, show_comments=False):
return self.render_string(
"module-entry.html", show_comments=show_comments)
即使一页中有多个相同的 UI 组件,UI 组件的 CSS 和 JavaScript 部分只会被渲染一次。 CSS 是在页面的 <head>
部分,而 JavaScript 被渲染在页面结尾 </body>
之前的位 置。
在不需要额外 Python 代码的情况下,模板文件也可以当做 UI 模块直接使用。 例如前面的例子可以以下面的方式实现,只要把这几行放到 module-entry.html
中就可以了:
{{ set_resources(embedded_css=".entry { margin-bottom: 1em; }") }}
<!-- more template html... -->
这个修改过的模块式模板可以通过下面的方法调用:
{% module Template("module-entry.html", show_comments=True) %}
set_resources
函数只能在 {% module Template(...) %}
调用的模板中访问到。 和 {% include ... %}
不同,模块式模板使用了和它们的上级模板不同的命名 空间——它们只能访问到全局模板命名空间和它们自己的关键字参数。