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

Tornado 模板

265次阅读
没有评论

共计 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、短信等云产品特惠热卖中