概述
使用模板 需要仿照静态资源文件路径设置 向web.Application类的构造函数传递一个名为 template_path的参数 来告诉tornado从文件系统的一个特定位置 提供模板文件
配置如下
BASE_DIR = os.path.dirname(__file__)
app = tornado.web.Application([
(<span class="hljs-string">r'/'</span>,IndexHandler),
], template_path=os.path.join(BASE_DIR,<span class="hljs-string">'templates'</span>),
debug=<span class="hljs-keyword">True</span>,
autoreload=<span class="hljs-keyword">True</span>,
)
我们设置了一个当前应用目录下名为templates的子目录作为template_path的参数。在handler中使用的模板将在此目录中寻找
目录结构
project/
static/
templates/
common/
index.html
manage.py
render(“模板名称”,**kwargs)
不传递参数示例
<span class="hljs-keyword">import</span> tornado.web
<span class="hljs-keyword">import</span> tornado.ioloop
<span class="hljs-keyword">import</span> os
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IndexHandler</span><span class="hljs-params">(tornado.web.RequestHandler)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
self.render(<span class="hljs-string">"index.html"</span>)
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
BASE_DIR = os.path.dirname(__file__)
app = tornado.web.Application([
(<span class="hljs-string">r'/'</span>,IndexHandler),
],
template_path=os.path.join(BASE_DIR,<span class="hljs-string">'templates'</span>),
debug=<span class="hljs-keyword">True</span>,
autoreload=<span class="hljs-keyword">True</span>,
)
app.listen(<span class="hljs-number">8000</span>)
tornado.ioloop.IOLoop.current().start()
传递参数示例
概述:
函数向模板中传递的参数 也就是变量 在模板中使用 {{ 变量名称 }} 进行获取值
处理类代码
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IndexHandler</span><span class="hljs-params">(tornado.web.RequestHandler)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
userInfo = {
<span class="hljs-string">'name'</span>:<span class="hljs-string">'lucky'</span>,
<span class="hljs-string">'age'</span>:<span class="hljs-number">18</span>,
<span class="hljs-string">'sex'</span>:<span class="hljs-string">'man'</span>,
<span class="hljs-string">'num'</span>: <span class="hljs-number">10</span>
}
<span class="hljs-comment"># 传递参数和flask一样</span>
<span class="hljs-comment"># 一次传递多个值</span>
self.render(<span class="hljs-string">"index.html"</span>,userInfo = userInfo)
模板文件代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>首页</h2>
<h4>获取传递的参数</h4>
<p>{{ userInfo }}</p>
<p>{{ userInfo['name'] }}</p>
<p>{{ userInfo['sex'] }}</p>
<p>{{ userInfo['age'] }}</p>
<h5>表达式(也就是可以在变量中进行运算操作)</h5>
<p>{{ userInfo['age'] + userInfo['num'] }}</p>
<h5>测试如果使用的变量不存在(也就是没有传递)结果为会报错</h5>
<p>{{ boy }}</p>
</body>
</html>
注意:
语法: {% tag %}
说明
可以在Tornado模板中 使用Python条件和循环语句 标签使用{% 标签名称 %} 来使用
作用
在输出中创建文本
控制逻辑和循环
if标签
格式
{% <span class="hljs-keyword">if</span> ...%}
...
{% <span class="hljs-keyword">elif</span> ... %}
...
{% <span class="hljs-keyword">else</span> %}
...
{% end %}
示例
{% if grade >= 90 %}
成绩优秀
{% elif grade >= 80 %}
成绩良好
{% else %}
成绩不太理想
{% end %}
for标签
格式
{% <span class="hljs-keyword">for</span> xx <span class="hljs-keyword">in</span> xx %}
循环体
{% end %}
示例
视图函数代码为:
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IndexHandler</span><span class="hljs-params">(tornado.web.RequestHandler)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
userInfo = {
<span class="hljs-string">'name'</span>:<span class="hljs-string">'lucky'</span>,
<span class="hljs-string">'age'</span>:<span class="hljs-number">18</span>,
<span class="hljs-string">'sex'</span>:<span class="hljs-string">'man'</span>,
<span class="hljs-string">'num'</span>:<span class="hljs-number">10</span>,
}
<span class="hljs-comment"># 传递参数和flask一样</span>
<span class="hljs-comment"># 一次传递多个值</span>
self.render(<span class="hljs-string">"index.html"</span>,userInfo = userInfo)
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TagHandler</span><span class="hljs-params">(tornado.web.RequestHandler)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
userInfo = {
<span class="hljs-string">'name'</span>: <span class="hljs-string">'lucky'</span>,
<span class="hljs-string">'age'</span>: <span class="hljs-number">18</span>,
<span class="hljs-string">'sex'</span>: <span class="hljs-string">'man'</span>,
<span class="hljs-string">'num'</span>: <span class="hljs-number">10</span>,
}
self.render(<span class="hljs-string">'test_tag.html'</span>,grade=<span class="hljs-number">70</span>,userInfo=userInfo)
模板代码
<ol>
{% for k,v in userInfo.items() %}
<li>{{ k }}----{{ v }}</li>
{% end %}
</ol>
转义
说明:tornado默认开启了模板自动转义功能 防止网站收到恶意攻击
示例
def get(self): self.render(“index.html”,html=“Hello Lucky”) ```
模板渲染结果为:
`<b>Hello Lucky</b>`
关闭转义的方式
第一种 raw 用来输出不被转义的原始格式
示例
{% raw html %} ```
第二种 设置关闭自动转义功能
在python配置中
```python
app = tornado.web.Application([], autoescape=None, ) ```
第三种 模板中
```phthon
{% autoescape None %} ```
转义变量
{{ escape(需要转义的变量) }} ```
模板导入 include
概述
可以将指定的HTML文件 在模板中的某个位置进行导入使用 实现模板代码的复用 以及减轻后期代码的维护
格式
{% include <span class="hljs-string">"路径/模板名称.html"</span> %}
示例
目录结构
project/
templates/
common/
header.html
footer.html
index.html
manage.py
index.html代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% include 'common/header.html' %}
<h2>首页</h2>
{% include 'common/footer.html' %}
</body>
</html>
header.html
<header>
<h4>头部分</h4>
</header>
footer.html
<footer>
<h4>尾部分</h4>
</footer>
注意事项
我们在使用include的时候 会将到入文件内的所有代码都拿过来 所以注意被导入的文件中不要有其它代码的存在 否则都会被导入过来
模板继承
标签:
extends 继承
格式
{% extends '父模板.html' %}
block 使用块填充
格式:
{% block '名称' %}
...
{% end %}
示例
目录结构
project/
templates/
common/
base.html
index.html
base.html代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}标题{% end %}</title>
</head>
<body>
{% block header %}
<h2>页面头部分</h2>
{% end %}
{% block content %}
<h2>页面内容部分</h2>
{% end %}
</body>
</html>
index.html
{% extends 'common/base.html' %}
{% block title %}
首页
{% end %}
{% block header %}
<h4>首页</h4>
{% end %}
使用bootstrap创建base模板
base.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}标题{% end %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
{% block styles %}
{% end %}
</head>
<body>
{% block header %}
<nav class="navbar navbar-inverse" style="border-radius: 0px;">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">首页 <span class="sr-only">(current)</span></a></li>
<li><a href="#">发表博客</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Search</button>
</form>
<li><a href="#">登录</a></li>
<li><a href="#">注册</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">个人中心<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">个人资料</a></li>
<li><a href="#">头像修改</a></li>
<li><a href="#">我的博客</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">退出登录</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{% end %}
<div class="container">
{% block content %}
<h1>你好,Lucky!</h1>
{% end %}
</div>
{% block scripts %}
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
{% end %}
</body>
</html>
注意
在子模板中 如果想对父母版中的哪个block的位置进行更改 那么就使用block 名称 进行替换 当替换以后 内容为你替换后的内容 若是没有进行替换 则内容为原内容
说明
在模板中还可以使用一个自己编写的函数 只需要将函数名作为模板的参数传递即可 就像其它变量一样
示例
处理类中
<span class="hljs-comment"># 自定义函数 在模板中进行使用</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_join</span><span class="hljs-params">(con)</span>:</span>
<span class="hljs-keyword">return</span> <span class="hljs-string">'+'</span>.join(con)
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IndexHandler</span><span class="hljs-params">(tornado.web.RequestHandler)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
self.render(<span class="hljs-string">"index.html"</span>,my_join=my_join)
模板中
<h4>传递函数在模板中使用</h4>
{{ my_join('lucky') }}
说明:我们的图片、样式、js效果 统称为我们的静态资源文件 需要配置静态资源目录static进行使用
目录结构
project/
static/
img/
css/
js/
upload/
manage.py
static_path
配置如下
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
app = tornado.web.Application(
[(<span class="hljs-string">r'/'</span>, IndexHandler)],
static_path=os.path.join(BASE_DIR, <span class="hljs-string">"static"</span>),
)
static_path 配置了静态资源访问的目录
代码示例
<span class="hljs-keyword">import</span> tornado.ioloop
<span class="hljs-keyword">import</span> tornado.httpserver
<span class="hljs-keyword">from</span> tornado.web <span class="hljs-keyword">import</span> RequestHandler, Application
<span class="hljs-keyword">import</span> os
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IndexHandler</span><span class="hljs-params">(RequestHandler)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
self.render(<span class="hljs-string">'index.html'</span>)
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
app = Application([
(<span class="hljs-string">r"/"</span>, IndexHandler),
],
static_path=os.path.join(BASE_DIR, <span class="hljs-string">"static"</span>),
template_path=os.path.join(BASE_DIR, <span class="hljs-string">"templates"</span>),
debug = <span class="hljs-keyword">True</span>,
)
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(<span class="hljs-number">8000</span>)
tornado.ioloop.IOLoop.current().start()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/test.css">
<script src="/static/js/test.js"></script>
</head>
<body>
<img src="/static/img/test.jpg" alt="">
</body>
</html>
注意:对于静态文件目录的命名,为了便于部署,建议使用static
模板中动态构造
格式
{{static_url('plugins/bootstrap/css/bootstrap.min.css')}}
示例
<img src="{{static_url('img/a.jpg')}}" alt="">
解析后
<img src="/static/img/test.jpg?v=11c671ed35a4611f3576ab4cbe5ee59c" alt="">
优点
前缀示例
BASE_DIR = os.path.dirname(__file__)
app = tornado.web.Application([
(<span class="hljs-string">r'^/$'</span>,IndexHandler),
],
template_path=os.path.join(BASE_DIR,<span class="hljs-string">'templates'</span>),
static_path=os.path.join(BASE_DIR,<span class="hljs-string">'static'</span>),
debug=<span class="hljs-keyword">True</span>,
static_url_prefix=<span class="hljs-string">'/lucky/'</span>,
)
直接通过url进行访问
http://127.0.0.1:8000/static/img/test.jpg
StaticFileHandler
说明
http://127.0.0.1:8000/static/img/test.jpg
,这中url显然对用户是不友好的,访问很不方便。我们可以通过tornado.web.StaticFileHandler来自由映射静态资源文件与其访问的路径url示例
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> tornado.web <span class="hljs-keyword">import</span> StaticFileHandler
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
app = Application(
[
(<span class="hljs-string">r'^/(.*?)$'</span>, StaticFileHandler, {<span class="hljs-string">"path"</span>:os.path.join(BASE_DIR, <span class="hljs-string">"static/img"</span>), <span class="hljs-string">"default_filename"</span>:<span class="hljs-string">"test.jpg"</span>}),
(<span class="hljs-string">r'^/view/(.*)$'</span>, StaticFileHandler, {<span class="hljs-string">"path"</span>:os.path.join(BASE_DIR, <span class="hljs-string">"static/img"</span>)}),
],
static_path=os.path.join(BASE_DIR, <span class="hljs-string">"static"</span>),
template_path=os.path.join(BASE_DIR, <span class="hljs-string">'templates'</span>),
)
模板中
<img src="/static/img/a.jpg" alt="">
<img src="/view/a.jpg" alt="">
<img src="/" alt="">
<img src="/b.jpg" alt="">
参数说明
path 用来指明提供静态文件的根路径,并在此目录中寻找在路由中用正则表达式提取的文件名
default_filename 用来指定访问路由中未指明文件名时,默认提供的文件
现在,对于静态文件statics/img/test.jpg,可以通过三种方式进行访问:
http://127.0.0.1:8000/static/img/test.jpg
http://127.0.0.1:8000/
http://127.0.0.1:8000/test.jpg
http://127.0.0.1:8000/view/test.jpg
文件上传注意事项
示例
<span class="hljs-keyword">import</span> tornado.web
<span class="hljs-keyword">import</span> tornado.ioloop
<span class="hljs-keyword">import</span> os
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IndexHandler</span><span class="hljs-params">(tornado.web.RequestHandler)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
self.render(<span class="hljs-string">'index.html'</span>)
<span class="hljs-comment"># 处理文件上传内的Handler</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UploadHandler</span><span class="hljs-params">(tornado.web.RequestHandler)</span>:</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
self.render(<span class="hljs-string">'upload.html'</span>)
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">post</span><span class="hljs-params">(self)</span>:</span>
<span class="hljs-comment"># 获取上传过来的文件</span>
files = self.request.files
<span class="hljs-keyword">if</span> files:
<span class="hljs-comment"># 取出包含当前上传文件数据的列表</span>
img = files.get(<span class="hljs-string">'img'</span>)
<span class="hljs-comment"># 获取上传文件名称(获取到文件名称 是不是可以自己通过文件名称判断该类型文件是否允许上传 以及生成新的文件唯一名称)</span>
filename = img[<span class="hljs-number">0</span>][<span class="hljs-string">'filename'</span>]
img_file = img[<span class="hljs-number">0</span>][<span class="hljs-string">'body'</span>]
<span class="hljs-comment"># 文件的存储操作</span>
<span class="hljs-comment"># 拼接文件上传存储路径</span>
path = os.path.join(<span class="hljs-string">'static/upload'</span>,filename)
file = open(path,<span class="hljs-string">'wb'</span>)
file.write(img_file)
file.close()
<span class="hljs-comment"># 上传成功还可以对文件进行大小缩放 以适应其他场合的使用</span>
self.write(<span class="hljs-string">'文件上传成功'</span>)
self.write(<span class="hljs-string">'来了老弟'</span>)
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
app = tornado.web.Application([
(<span class="hljs-string">r'/'</span>,IndexHandler),
(<span class="hljs-string">r'/upload/'</span>,UploadHandler),
],
debug=<span class="hljs-keyword">True</span>,
autoreload=<span class="hljs-keyword">True</span>,
template_path=os.path.join(os.path.dirname(__file__),<span class="hljs-string">'templates'</span>),
)
app.listen(<span class="hljs-number">8000</span>)
tornado.ioloop.IOLoop.current().start()
upload.html
{% extends 'common/base.html' %}
{% block title %}
文件上传
{% end %}
{% block content %}
<div class="page-header"><h2>文件上传</h2></div>
<form action="/upload/" method="post" enctype="multipart/form-data">
<p><input type="file" name="img"></p>
<p><input type="submit" value="上传"></p>
</form>
{% end %}