前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Tornado 模板

Tornado 模板

作者头像
星哥玩云
发布2022-09-14 19:03:55
1.2K0
发布2022-09-14 19:03:55
举报
文章被收录于专栏:开源部署

一、模板配置

概述

使用模板 需要仿照静态资源文件路径设置 向web.Application类的构造函数传递一个名为 template_path的参数 来告诉tornado从文件系统的一个特定位置 提供模板文件

配置如下

代码语言:javascript
复制
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中使用的模板将在此目录中寻找

目录结构

代码语言:javascript
复制
project/
	static/
	templates/
    	common/
      index.html
    manage.py

二、模板渲染

render(“模板名称”,**kwargs)

不传递参数示例

代码语言:javascript
复制
<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()

传递参数示例

概述:

函数向模板中传递的参数 也就是变量 在模板中使用 {{ 变量名称 }} 进行获取值

处理类代码

代码语言:javascript
复制
<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)

模板文件代码

代码语言:javascript
复制
<!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>

注意:

  • 如果在模板中使用了未传递的变量 则报错
  • 视图传递给模板的数据
  • 要遵守标识符规则
  • 语法:{{ var }}

三、标签

语法: {% tag %}

说明

可以在Tornado模板中 使用Python条件和循环语句 标签使用{% 标签名称 %} 来使用

作用

在输出中创建文本

控制逻辑和循环

if标签

格式

代码语言:javascript
复制
{% <span class="hljs-keyword">if</span> ...%}
	...
{% <span class="hljs-keyword">elif</span> ... %}  
	...
{% <span class="hljs-keyword">else</span> %}  
	...
{% end %}

示例

代码语言:javascript
复制
{% if grade >= 90 %}
    成绩优秀
{% elif grade >= 80 %}
    成绩良好
{% else %}
    成绩不太理想
{% end %}

for标签

格式

代码语言:javascript
复制
{% <span class="hljs-keyword">for</span> xx <span class="hljs-keyword">in</span> xx %} 
	循环体 
{% end %}

示例

视图函数代码为:

代码语言:javascript
复制
<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)

模板代码

代码语言:javascript
复制
<ol>
    {% for k,v in userInfo.items() %}
        <li>{{ k }}----{{ v }}</li>
    {% end %}
</ol>

转义

说明:tornado默认开启了模板自动转义功能 防止网站收到恶意攻击

示例

代码语言:javascript
复制

def get(self): self.render(“index.html”,html=“Hello Lucky”) ```

代码语言:javascript
复制
模板渲染结果为:

`&lt;b&gt;Hello Lucky&lt;/b&gt;`

关闭转义的方式

第一种 raw 用来输出不被转义的原始格式

示例

代码语言:javascript
复制

{% raw html %} ```

代码语言:javascript
复制
第二种 设置关闭自动转义功能

在python配置中

```python

app = tornado.web.Application([], autoescape=None, ) ```

代码语言:javascript
复制
第三种 模板中

```phthon

{% autoescape None %} ```

转义变量

代码语言:javascript
复制

{{ escape(需要转义的变量) }} ```

模板导入 include

概述

可以将指定的HTML文件 在模板中的某个位置进行导入使用 实现模板代码的复用 以及减轻后期代码的维护

格式

代码语言:javascript
复制
{% include <span class="hljs-string">"路径/模板名称.html"</span> %}

示例

目录结构

代码语言:javascript
复制
project/
	templates/
    	common/
        	header.html
            footer.html
        index.html
    manage.py

index.html代码如下

代码语言:javascript
复制
<!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

代码语言:javascript
复制
<header>
    <h4>头部分</h4>
</header>

footer.html

代码语言:javascript
复制
<footer>
    <h4>尾部分</h4>
</footer>

注意事项

我们在使用include的时候 会将到入文件内的所有代码都拿过来 所以注意被导入的文件中不要有其它代码的存在 否则都会被导入过来

模板继承

标签:

extends 继承

格式

代码语言:javascript
复制
{% extends '父模板.html' %}

block 使用块填充

格式:

代码语言:javascript
复制
{% block '名称' %}
	...
{% end %}

示例

目录结构

代码语言:javascript
复制
project/
	templates/
    	common/
        	base.html
        index.html

base.html代码如下

代码语言:javascript
复制
<!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

代码语言:javascript
复制
{% extends 'common/base.html' %}
{% block title %}
    首页
{% end %}
{% block header %}
    <h4>首页</h4>
{% end %}

使用bootstrap创建base模板

base.html

代码语言:javascript
复制
<!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 名称 进行替换 当替换以后 内容为你替换后的内容 若是没有进行替换 则内容为原内容

四、自定义函数

说明

在模板中还可以使用一个自己编写的函数 只需要将函数名作为模板的参数传递即可 就像其它变量一样

示例

处理类中

代码语言:javascript
复制
<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)

模板中

代码语言:javascript
复制
<h4>传递函数在模板中使用</h4>
{{ my_join('lucky') }}

五、静态文件

说明:我们的图片、样式、js效果 统称为我们的静态资源文件 需要配置静态资源目录static进行使用

目录结构

代码语言:javascript
复制
project/
	static/
		img/
		css/
		js/
		upload/
	manage.py

static_path

  • 说明:我们可以通过向web.Application类的构造函数传递一个名为static_path的参数来告诉Tornado从文件系统的一个特定位置提供静态文件

配置如下

代码语言:javascript
复制
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 配置了静态资源访问的目录

代码示例

代码语言:javascript
复制
<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

代码语言:javascript
复制
<!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

模板中动态构造

格式

代码语言:javascript
复制
{{static_url('plugins/bootstrap/css/bootstrap.min.css')}}

示例

代码语言:javascript
复制
<img src="{{static_url('img/a.jpg')}}" alt="">

解析后

代码语言:javascript
复制
<img src="/static/img/test.jpg?v=11c671ed35a4611f3576ab4cbe5ee59c" alt="">

优点

  • static_url 函数创建了一个基于文件内容的hash值 并将其添加到URL末尾(查询字符串的参数v) 这个hash值确保浏览器总是加载一个文件的最新版 而不是之前的缓存版本 无论是在应用到开发阶段 还是在部署环境中 都非常有用 因为用户不必在为了看到最新的页面内容而清除浏览器缓存了
  • 另外一个好处可以动态改变应用URL的结构 而不需要改变模板中的代码 需要配置 static_url_prefix来进行更改 如果你使用它进行了更改 那么模板中不需要改变

前缀示例

代码语言:javascript
复制
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
  • urltornado.web.StaticFileHandler是tornado预置的用来提供静态资源文件的handler

示例

代码语言:javascript
复制
<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>),
)

模板中

代码语言:javascript
复制
<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

六、文件上传

文件上传注意事项

  • 表单的enctype注意修改在进行文件上传的时候
  • 文件上传的文本域 需要存在name属性值
  • 提交方式为 post

示例

代码语言:javascript
复制
<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

代码语言:javascript
复制
{% 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 %}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、模板配置
  • 二、模板渲染
  • 三、标签
  • 四、自定义函数
  • 五、静态文件
  • 六、文件上传
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档