2.1 简单示例:Poem Maker Pro
让我们以一个叫作 Poem Maker Pro 的简单例子开始。Poem Maker Pro 这个 Web 应用有一个让用户填写的 HTML 表单,然后处理表单的结果。代码清单 2-1 是它的 Python 代码。
代码清单 2-1 简单表单和模板:poemmaker.py
import os.path
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html')
class PoemPageHandler(tornado.web.RequestHandler):
def post(self):
noun1 = self.get_argument('noun1')
noun2 = self.get_argument('noun2')
verb = self.get_argument('verb')
noun3 = self.get_argument('noun3')
self.render('poem.html', roads=noun1, wood=noun2, made=verb,
difference=noun3)
if __name__ == '__main__':
tornado.options.parse_command_line()
app = tornado.web.Application(
handlers=[(r'/', IndexHandler), (r'/poem', PoemPageHandler)],
template_path=os.path.join(os.path.dirname(__file__), "templates")
)
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
除了 poemmaker.py,你还需要将代码清单 2-2 和代码清单 2-3 中的两个文件加入到 templates 子文件夹中。
代码清单 2-2 Poem Maker 表单:index.html
<!DOCTYPE html>
<html>
<head><title>Poem Maker Pro</title></head>
<body>
<h1>Enter terms below.</h1>
<form method="post" action="/poem">
<p>Plural noun<br><input type="text" name="noun1"></p>
<p>Singular noun<br><input type="text" name="noun2"></p>
<p>Verb (past tense)<br><input type="text" name="verb"></p>
<p>Noun<br><input type="text" name="noun3"></p>
<input type="submit">
</form>
</body>
</html>
代码清单 2-3 Poem Maker 模板:poem.html
<!DOCTYPE html>
<html>
<head><title>Poem Maker Pro</title></head>
<body>
<h1>Your poem</h1>
<p>Two {{roads}} diverged in a {{wood}}, and I—<br>
I took the one less travelled by,<br>
And that has {{made}} all the {{difference}}.</p>
</body>
</html>
在命令行执行下述命令:
$ python poemmaker.py --port=8000
现在,在浏览器中打开 http://localhost:8000 。当浏览器请求根目录(/)时,Tornado 程序将渲染 index.html,展示如图 2-1 所示的简单 HTML 表单。
图 2-1 Poem Maker Pro:输入表单
这个表单包括多个文本域(命名为 noun1、noun2 等),其中的内容将在用户点击"Submit"按钮时以 POST 请求的方式送到 /poem
。现在往里面填写东西然后点击提交吧。
为了响应这个 POST 请求,Tornado 应用跳转到 poem.html,插入你在表单中填写的值。结果是 Robert Frost 的诗《The Road Not Taken》的轻微修改版本。图 2-2 展示了这个结果。
图 2-2 Poem Maker Pro:输出
2.1.1 渲染模板
从结构上讲,poemmaker.py 和 第一章 中的例子很相似。我们定义了几个 RequestHandler 子类并把它们传给 tornado.web.Application 对象。那么有什么不一样的地方呢?首先,我们向 Application 对象的 init 方法传递了一个 template_path 参数。
template_path=os.path.join(os.path.dirname(__file__), "templates")
template_path 参数告诉 Tornado 在哪里寻找模板文件。我们将在本章和 第三章 中讲解其确切性质和语法,而它的基本要点是:模板是一个允许你嵌入 Python 代码片段的 HTML 文件。上面的代码告诉 Python 在你 Tornado 应用文件同目录下的 templates 文件夹中寻找模板文件。
一旦我们告诉 Tornado 在哪里找到模板,我们可以使用 RequestHandler 类的 render 方法来告诉 Tornado 读入模板文件,插入其中的模版代码,并返回结果给浏览器。比如,在 IndexHandler 中,我们发现了下面的语句:
self.render('index.html')
这段代码告诉 Tornado 在 templates 文件夹下找到一个名为 index.html 的文件,读取其中的内容,并且发送给浏览器。
2.1.2 填充
实际上 index.html 完全不能称之为"模板",它所包含的完全是已编写好的 HTML 标记。这可以是模板的一个不错的使用方式,但在更通常的情况下我们希望 HTML 输出可以结合我们的程序传入给模板的值。模板 poem.html 使用 PoemPageHandler 渲染,是这种方式的一个很好的例子。让我们看看它是如何工作的吧。
在 poem.html 中,你可以看到模板中有一些被双大括号({{和}})括起来的字符串,就像这样:
<p>Two {{roads}} diverged in a {{wood}}, and I—<br/>
I took the one less travelled by,<br>
And that has {{made}} all the {{difference}}.</p>
在双大括号中的单词是占位符,当我们渲染模板时希望以实际值代替。我们可以使用向 render 函数中传递关键字参数的方法指定什么值将被填充到 HTML 文件中的对应位置,其中关键字对应模板文件中占位符的名字。下面是在 PoemPageHandler 中相应的代码部分:
noun1 = self.get_argument('noun1')
noun2 = self.get_argument('noun2')
verb = self.get_argument('verb')
noun3 = self.get_argument('noun3')
self.render('poem.html', roads=noun1, wood=noun2, made=verb, difference=noun3)
在这里,我们告诉模板使用变量 noun1(该变量是从 get_argument 方法取得的)作为模板中 roads 的值,noun2 作为模板中 wood 的值,依此类推。假设用户在表单中按顺序键入了 pineapples、grandfather clock、irradiated 和 supernovae,那么结果 HTML 将会如下所示:
<p>Two pineapples diverged in a grandfather clock, and I—<br>
I took the one less travelled by,<br>
And that has irradiated all the supernovae.</p>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论