模板
在tornado中,模板就是一个html文件,
但是模板通过模板语法,由tornado服务渲染之后,可以动态的往页面中填入数据
tornado自带模板语法,不需要再用其他的模板插件
模板就是格式固定的网页:格式是固定的,内容是变化的
模板是一个允许嵌入Python代码片段的HTML文件
配置路径
在 application 中配置模板文件和静态文件的路径:
template_path='templates',
static_path='static',
把html文件放入'templates'文件夹下
把静态文件放入'static'文件夹下
模板
<body>
欢迎{{ username }}登录
</body>
Handler
在handler中使用 render()方法来渲染模板 并返回给客户端。
class TemHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.write('templates')
self.render('03templates.html')
def post(self, *args, **kwargs):
user = self.get_argument('name', 'no')
self.render('03templates1.html', username=user) # 渲染主页模板,并返回给客户端
这段代码告诉Tornado在templates文件夹下找到一个名为03templates.html 的文件,读取其中的内容,并且发送给浏览器
# coding:utf-8
import tornado.web
import tornado.ioloop
import tornado.options
import tornado.httpserver
from tornado.options import define, options
define('port', default=8000, type=int, help='port')
class TemHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.write('templates')
self.render('03templates.html')
def post(self, *args, **kwargs):
user = self.get_argument('name', 'no')
self.render('03templates1.html', username=user) # 渲染主页模板,并返回给客户端
application = tornado.web.Application(
handlers=[
(r'/tem', TemHandler),
],
template_path='template',
debug=True
)
if __name__ == '__main__':
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.current().start()
03templates.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello world
<form method="post" action="/tem">
<p>用户名:<input type="text" name="name"></p>
<p>密 码:<input type="password" name="password"></p>
<input type="submit">
</form>
</body>
</html>
03templates1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
欢迎{{username}}登录
</body>
</html>
模板语法
模板符号
{{ expression }} 表达式
用 {{ expression }} 中间是任何 python 表达式,或者是一个变量
{{ 1 + 1 }} 传入一个表达式
{{ a = 1 + 2 }}
{{ time.time() }} 可以执行函数
{{ haha() }} 自定义的函数也可以传入
import time
self.render('03templates1.html',time=time,)
03templates1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
欢迎{{ username }}登录
<br>
{{ 1+1 }}
<br>
{{ a=2+3 }}
<br>
{{ time.time() }}
<!--时间戳-->
{{ haha() }}
<br>
</body>
</html>
页面显示
欢迎e登录
2
5
1535034081.0445783
hahahah
# coding:utf-8
import tornado.web
import tornado.ioloop
import tornado.options
import tornado.httpserver
import time
from tornado.options import define, options
define('port', default=8000, type=int, help='port')
class TemHandler(tornado.web.RequestHandler):
def haha(self):
return 'hahahah'
def get(self, *args, **kwargs):
self.write('templates')
self.render('03templates.html')
def post(self, *args, **kwargs):
user = self.get_argument('name', 'no')
self.render('03templates1.html',
username=user,
haha = self.haha,
time=time
)
application = tornado.web.Application(
handlers=[
(r'/tem', TemHandler),
],
template_path='template',
debug=True
)
if __name__ == '__main__':
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.current().start()
03templates.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello world
<form method="post" action="/tem">
<p>用户名:<input type="text" name="name"></p>
<p>密 码:<input type="password" name="password"></p>
<input type="submit">
</form>
</body>
</html>
{% directives %} if for while
其他的模板指令
{% if 1 %}
this is if
{% end %}
{% if username != 'no' %}
欢迎{{ username }}登录
{% end %}
if后面一定要加上end
{# … #} 注释
在模板中要注释python表达式的运行,需要使用这个模板语法
{# time.time() #}}
{{! {%! {#!
如果不想执行内容,需要在页面上打印出模板符号,只需要加上感叹号( ! )即可
{{! 1 + 1}}
{%! if 1 %}
this is if
{%! end %}
{#! time.time() #}
页面显示
{{ 1 + 1}}
{% if 1 %} this is if {% end %}
{# time.time() #}
控制语句
if判断
在模板中可以使用 if 判断注意:最后需要以 {% end %} 结尾
{% if username != 'no' %}
欢迎{{ username }}登录
{% else %}
请登录
{% end %}
{% if ... %} ... {% elif ... %} ... {% else ... %} ... {% end %}
for 循环
{% for … in … %} … {% end %}
在 tornado 模板中可以使用 for 循环注意:最后需要以 {% end %} 结尾
urllist = [
('https://www.baidu.com', '百度'),
('https://www.shiguangkey.com', '时光课堂')
]
{% for i in urllist %}
{{ i }}
{% end %}
# coding:utf-8
import tornado.web
import tornado.ioloop
import tornado.options
import tornado.httpserver
import time
from tornado.options import define, options
define('port', default=8000, type=int, help='port')
class TemHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.write('templates')
self.render('03templates.html')
def post(self, *args, **kwargs):
user = self.get_argument('name', 'no')
urllist = [
('https://www.baidu.com', '百度'),
('https://www.shiguangkey.com', '时光课堂')
]
self.render('03templates1.html',
username=user,
time=time,
urllist = urllist,
) # 渲染主页模板,并返回给客户端
application = tornado.web.Application(
handlers=[
(r'/tem', TemHandler),
],
template_path='template',
debug=True
)
if __name__ == '__main__':
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.current().start()
03templates1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% if username != 'no' %}
欢迎{{ username }}登录
{% end %}
<br>
{{ 1+1 }}
<br>
{{ a=2+3 }}
<br>
{{ time.time() }}
<!--时间戳-->
<br>
{% for i in urllist %}
<a href="{{ i[0] }}" target="_blank">{{ i[1] }}</a>
{% end %}
</body>
</html>
03templates.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello world
<form method="post" action="/tem">
<p>用户名:<input type="text" name="name"></p>
<p>密 码:<input type="password" name="password"></p>
<input type="submit">
</form>
</body>
</html>
页面显示效果如下
欢迎o登录
2
5
1534072276.9205718
while 循环
在 tornado 模板中可以使用 while 循环注意:最后需要以 {% end %} 结尾
#设置变量
{% set a = 0 %}
{% while a<5 %}
{{ a }} <br>
{% set a += 1 %}
{% end %}
{% while ... %} ... {% end %}
模板转义
模板转义
参数
atga = "<a href='https://www.baidu.com' target='_blank'>___百度___</a><br>"
模板
{{ atga }}
页面显示
<a href='https://www.baidu.com' target='_blank'>___百度___</a><br>
转义
tornado默认是自动的转义,传入的数据都会当作字符串,即:
<a href='https://www.baidu.com' target='_blank'>___百度___</a><br>
< 变为 <
浏览器再进行解析 变为
<a href='https://www.baidu.com' target='_blank'>___百度___</a><br>
显示到客户端
把所有的输出都作为字符串,这样做的就能防止一些恶意代码在输出到前端时被执行,从而造成数据泄露。
当然这个默认自动是转义的,如果不要转义也是可以的,有如下方法:
模板去掉转义
局部去掉转义
{% raw atga %}
raw
raw 可以自模板中去掉转义,让 tornado 在渲染的时候不去转义变量
class IndexHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.render('01in_out.html')
def post(self, *args, **kwargs):
atga = "<a href='https://www.baidu.com' target='_blank'>___百度___</a><br>"
self.render(
'03template.html',
atga=atga
)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ atga }}
<br>
{% raw atga %}
<br>
</body>
</html>
页面显示
<a href='https://www.baidu.com' target='_blank'>___百度___</a><br>
https://www.baidu.com’ target=’_blank’>百度
模板去转义
{% autoescape None %}
autoescape
在模板中添加上面代码之后,当前模板不再转义
<!DOCTYPE html>
{% autoescape None %} <!--告诉tornado不需要转义-->
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ atga }}
<br>
{% raw atga %}
<br>
</body>
</html>
页面显示
全局去掉转义
在 Application 中添加如下配置:
autoescape=None,
application = tornado.web.Application(
handlers=[
(r'/tem', TemHandler),
],
template_path='template',
autoescape = None,
debug=True
)
autoescape
这个是去掉整个项目的转义
所有子域名 下都不转义
此路由 下都不转义
escape
在开启全局和文档不转义的情况下,可以使用 escape() 来开启变量的转义
{{ escape(atga) }}
在开启模板不转义之后,可以使用 escape 来添加转义
<!DOCTYPE html>
{% autoescape None %} <!--告诉tornado不需要转义-->
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ atga }}
<br>
{% raw atga %}
<br>
{{ escape(atga) }}
<br>
</body>
</html>
页面显示
<a href='https://www.baidu.com' target='_blank'>___百度___</a><br>
tornado是默认自动开启转义的,大家可以根据需求来选是否转义,但是要知道转义的本意是来防止浏览器意外执行恶意代码的,所以去掉转义的时候需要谨慎选择。
静态文件引用
Application
static_path='statics',
application = tornado.web.Application(
handlers=[
(r'/', IndexHandler),
(r'/tem', TemHandler),
],
template_path='template',
static_path='statics',
autoescape = None,
debug=True
)
路由配置
添加此配置之后,tornado就能自己找到静态文件
两种引入方式
<img src="{{ static_url('images/c.jpg') }}" width="250" height="250">
<img src="static/images/c.jpg" width="250" height="250">
static_url
使用此方法,需要配置好 static_path
使用这个方法可以不用担心路径变更问题
使用此方法时,Tornado 会自动地给静态文件添加版本号,如果版本号更改了,浏览器会自动的缓存新的静态文件,不需要清除缓存了
<img src="/static/images/b.jpg?v=7bf9390864dcae4d3cbdc4f9562fc2c1" width="250">
static/
<img src="static/images/c.jpg" width="250" height="250">
自动查找
在 Tornado 模板中,static 是个关键词,不是文件夹的名字 ,能够自动替换成 static_path 后的内容,即使 static_path='statics',
代码
# coding:utf-8
import tornado.web
import tornado.ioloop
import tornado.options
import tornado.httpserver
import time
from tornado.options import define, options
define('port', default=8000, type=int, help='port')
class IndexHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.write('hello')
class TemHandler(tornado.web.RequestHandler):
def haha(self):
return 'hahahah'
def get(self, *args, **kwargs):
self.write('templates')
self.render('03templates.html')
def post(self, *args, **kwargs):
user = self.get_argument('name', 'no')
urllist = [
('https://www.baidu.com', '百度'),
('https://www.shiguangkey.com', '时光课堂')
]
atga = "<a href='https://www.baidu.com' target='_blank'>___百度___</a><br>"
self.render('03templates1.html',
username=user,
time=time,
urllist = urllist,
atga = atga,
haha = self.haha,
) # 渲染主页模板,并返回给客户端
application = tornado.web.Application(
handlers=[
(r'/', IndexHandler),
(r'/tem', TemHandler),
],
template_path='template',
static_path='statics',
autoescape = None,
debug=True
)
if __name__ == '__main__':
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.current().start()
03templates1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{# autoescape None #}
{% if username != 'no' %}
欢迎{{ username }}登录
<img src="static/images/a.jpg" width="250">
<img src="{{static_url('images/b.jpg')}}" width="250">
{% else %}
请登录
{% end %}
<br>
{{ 1+1 }}
<br>
{{ a=2+3 }}
<br>
{{ time.time() }}
<!--时间戳-->
<br>
{% for i in urllist %}
{{ i }}<br>
{% end %}
<br>
{% for i in urllist %}
<a href="{{ i[0] }}" target="_blank">{{ i[1] }}</a><br>
{% end %}
<br>
{% set a = 0 %}
{% while a<5 %}
{{a}}<br>
{% set a += 1 %}
{% end %}
<br>
{{ atga }}
<br>
{% raw atga %}
<br>
{{ escape(atga) }}
<br>
</body>
</html>
03templates.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello world
<form method="post" action="/tem">
<p>用户名:<input type="text" name="name"></p>
<p>密 码:<input type="password" name="password"></p>
<input type="submit">
</form>
</body>
</html>