Forms and Templates
ex poem maker pro
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)
新建两个类,注意最后返回的页面是使用render()来进行渲染的,模板分别是index.html和poem.html,render函数还可以带关键字参数
现在在工程目录下建立目录templates用来放置html模板文件,同时在Application类里增加新目录的路径:
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()
template_path指明查找模板文件的路径
下面是html文件,tornado的模板与django的类似
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>
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>
template syntax
模板中的{{ var }}表示变量,运行时会被替换为这个变量的真实的值,这里是通过self.render('poem.html', roads=noun1, wood=noun2,...)传递到模板的 {{ }}中还可以是python的表达式,执行时会对表达式先求值再进行替换
>>> from tornado.template import Template
>>> print Template("{{1+1}}").generate()
2
>>> print Template("{{', '.join([str(x*x) for x in range(10)]) }}").generate()
0, 1, 4, ... , 81
control flow statements
条件控制语句放在{% %}中
eg,
<html>
<head>
...
</head>
<body>
<h1>{{header}}</h1>
<ul>
{% for book in books %}
<li>{{ book }}</li>
{% end %}
</ul>
</body>
</html>
using functions in templates
- escape(s) : 将字符串s中的&,<,>替换为相应的html对象
- url_escape(s)
- json_encode(val)
- squeeze(s): 将超过一个的连续空格符替换为一个
将函数传递到模板中:只要将函数名字作为参数放在generate()函数中,eg,
>>> from tornado.template import Template
>>> def disemvowel(s):
... return ''.join([x for x in s if x not in 'aeiou'])
...
>>> disemvowel("george")
'grg'
>>> print Template("my name is {{d('mortimer')}}").generate(d=disemvowel)
my name is mrtmr
static files
类似模板的方法,先建立目录static,然后在Application中添加路径
app = tornado.web.Application(
handlers=[(r'/', IndexHandler), (r'/poem', MungedPageHandler)],
template_path=os.path.join(os.path.dirname(__file__), "templates"),
static_path=os.path.join(os.path.dirname(__file__), "static"),
debug=True
)
这里设置debug=True后,只要修改服务器代码,会自动重启服务器来使用这些修改
static文件夹可以放置css,js,jpg等静态文件,这些文件可以用static_url来得到访问的url,如在index.html中,
<link rel="stylesheet" href="{{ static_url("style.css") }}">
运行时static_url会得到一个真实的url值,链接将会类似与这种形式:
<link rel=... href="/static/style.css?v=ab12">
使用static_url来得到url而不是直接写上真实url,目的是减少硬编码