阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Tornado 模板

482次阅读
没有评论

共计 9879 个字符,预计需要花费 25 分钟才能阅读完成。

一、模板配置

  • 概述

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

  • 配置如下

    BASE_DIR = os.path.dirname(__file__) app = tornado.web.Application([(r'/',IndexHandler), ], template_path=os.path.join(BASE_DIR,'templates'), debug=True, autoreload=True, )

    我们设置了一个当前应用目录下名为 templates 的子目录作为 template_path 的参数。在 handler 中使用的模板将在此目录中寻找

  • 目录结构

    project/ static/ templates/ common/ index.html manage.py

二、模板渲染

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

    不传递参数示例

    import tornado.web import tornado.ioloop import os class IndexHandler(tornado.web.RequestHandler): def get(self): self.render("index.html") if __name__ == '__main__': BASE_DIR = os.path.dirname(__file__) app = tornado.web.Application([(r'/',IndexHandler), ], template_path=os.path.join(BASE_DIR,'templates'), debug=True, autoreload=True, ) app.listen(8000) tornado.ioloop.IOLoop.current().start()

    传递参数示例

    概述:

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

    处理类代码

    class IndexHandler(tornado.web.RequestHandler): def get(self): userInfo = {'name':'lucky', 'age':18, 'sex':'man', 'num': 10 } # 传递参数和 flask 一样 # 一次传递多个值 self.render("index.html",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>

    注意:

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

三、标签

  • 语法: {% tag %}

  • 说明

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

  • 作用

    在输出中创建文本

    控制逻辑和循环

  • if 标签

    格式

    {% if ...%} ... {% elif ... %} ... {% else %} ... {% end %}

    示例

    {% if grade >= 90 %} 成绩优秀 {% elif grade >= 80 %} 成绩良好 {% else %} 成绩不太理想 {% end %}
  • for 标签

    格式

    {% for xx in xx %} 循环体 {% end %}

    示例

    视图函数代码为:

    class IndexHandler(tornado.web.RequestHandler): def get(self): userInfo = {'name':'lucky', 'age':18, 'sex':'man', 'num':10, } # 传递参数和 flask 一样 # 一次传递多个值 self.render("index.html",userInfo = userInfo) class TagHandler(tornado.web.RequestHandler): def get(self): userInfo = {'name': 'lucky', 'age': 18, 'sex': 'man', 'num': 10, } self.render('test_tag.html',grade=70,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”)
“`

 模板渲染结果为:`&lt;b&gt;Hello Lucky&lt;/b&gt;`
  • 关闭转义的方式

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

    示例

{% raw html %}
“`

 第二种 设置关闭自动转义功能

在 python 配置中

```python

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

 第三种 模板中

```phthon

{% autoescape None %}
“`

  • 转义变量

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

  • 模板导入 include

    • 概述

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

    • 格式

      {% include "路径 / 模板名称.html" %}
    • 示例

      目录结构

      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 名称 进行替换 当替换以后 内容为你替换后的内容 若是没有进行替换 则内容为原内容

四、自定义函数

  • 说明

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

  • 示例

    处理类中

    # 自定义函数 在模板中进行使用 def my_join(con): return '+'.join(con) class IndexHandler(tornado.web.RequestHandler): def get(self): self.render("index.html",my_join=my_join)

    模板中

    <h4> 传递函数在模板中使用 </h4> {{my_join('lucky') }}

五、静态文件

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

  • 目录结构

    project/ static/ img/ css/ js/ upload/ manage.py
  • static_path

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

    BASE_DIR = os.path.dirname(os.path.abspath(__file__)) app = tornado.web.Application([(r'/', IndexHandler)], static_path=os.path.join(BASE_DIR, "static"), )

    static_path 配置了静态资源访问的目录

    • 代码示例

      import tornado.ioloop import tornado.httpserver from tornado.web import RequestHandler, Application import os class IndexHandler(RequestHandler): def get(self): self.render('index.html') if __name__ == "__main__": BASE_DIR = os.path.dirname(os.path.abspath(__file__)) app = Application([(r"/", IndexHandler), ], static_path=os.path.join(BASE_DIR, "static"), template_path=os.path.join(BASE_DIR, "templates"), debug = True, ) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(8000) 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="">

      优点

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

      前缀示例

      BASE_DIR = os.path.dirname(__file__) app = tornado.web.Application([(r'^/$',IndexHandler), ], template_path=os.path.join(BASE_DIR,'templates'), static_path=os.path.join(BASE_DIR,'static'), debug=True, static_url_prefix='/lucky/', )
    • 直接通过 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
    • 示例

      import os from tornado.web import StaticFileHandler BASE_DIR = os.path.dirname(os.path.abspath(__file__)) app = Application( [(r'^/(.*?)$', StaticFileHandler, {"path":os.path.join(BASE_DIR, "static/img"), "default_filename":"test.jpg"}), (r'^/view/(.*)$', StaticFileHandler, {"path":os.path.join(BASE_DIR, "static/img")}), ], static_path=os.path.join(BASE_DIR, "static"), template_path=os.path.join(BASE_DIR, 'templates'), )

      模板中

      <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

示例

import tornado.web import tornado.ioloop import os class IndexHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') # 处理文件上传内的 Handler class UploadHandler(tornado.web.RequestHandler): def get(self): self.render('upload.html') def post(self): # 获取上传过来的文件 files = self.request.files if files: # 取出包含当前上传文件数据的列表 img = files.get('img') # 获取上传文件名称 (获取到文件名称 是不是可以自己通过文件名称判断该类型文件是否允许上传 以及生成新的文件唯一名称) filename = img[0]['filename'] img_file = img[0]['body'] # 文件的存储操作 # 拼接文件上传存储路径 path = os.path.join('static/upload',filename) file = open(path,'wb') file.write(img_file) file.close() # 上传成功还可以对文件进行大小缩放 以适应其他场合的使用 self.write('文件上传成功') self.write('来了老弟') if __name__ == '__main__': app = tornado.web.Application([(r'/',IndexHandler), (r'/upload/',UploadHandler), ], debug=True, autoreload=True, template_path=os.path.join(os.path.dirname(__file__),'templates'), ) app.listen(8000) 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 %}

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-05-26发表,共计9879字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7999472
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛 NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手! 作为动漫爱好者,你是否还在为...
你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你 为什么要用宝塔跑分? 宝塔跑分其实就是对 CPU、内存、磁盘、IO 做...
浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍 前言 在 AI 自动化快速发展的当下,浏览器早已不再只是...
每年0.99刀,拿下你的第一个顶级域名,详细注册使用

每年0.99刀,拿下你的第一个顶级域名,详细注册使用

每年 0.99 刀,拿下你的第一个顶级域名,详细注册使用 前言 作为长期折腾云服务、域名建站的老玩家,星哥一直...
仅2MB大小!开源硬件监控工具:Win11 无缝适配,CPU、GPU、网速全维度掌控

仅2MB大小!开源硬件监控工具:Win11 无缝适配,CPU、GPU、网速全维度掌控

还在忍受动辄数百兆的“全家桶”监控软件?后台偷占资源、界面杂乱冗余,想查个 CPU 温度都要层层点选? 今天给...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
开发者福利:免费 .frii.site 子域名,一分钟申请即用

开发者福利:免费 .frii.site 子域名,一分钟申请即用

  开发者福利:免费 .frii.site 子域名,一分钟申请即用 前言 在学习 Web 开发、部署...
免费无广告!这款跨平台AI RSS阅读器,拯救你的信息焦虑

免费无广告!这款跨平台AI RSS阅读器,拯救你的信息焦虑

  免费无广告!这款跨平台 AI RSS 阅读器,拯救你的信息焦虑 在算法推荐主导信息流的时代,我们...
颠覆 AI 开发效率!开源工具一站式管控 30+大模型ApiKey,秘钥付费+负载均衡全搞定

颠覆 AI 开发效率!开源工具一站式管控 30+大模型ApiKey,秘钥付费+负载均衡全搞定

  颠覆 AI 开发效率!开源工具一站式管控 30+ 大模型 ApiKey,秘钥付费 + 负载均衡全...
支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare 也瘫了连监控都挂,根因藏在哪? 最近两天的互联网堪称“故障...
12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换...