4.1 静态文件

现在有一个预先写好的静态页面文件 (下载静态文件资源), 我们来看下如何用tornado提供静态文件。

static_path

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

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

在这里,我们设置了一个当前应用目录下名为statics的子目录作为static_path的参数。现在应用将以读取statics目录下的filename.ext来响应诸如/static/filename.ext的请求,并在响应的主体中返回。

对于静态文件目录的命名,为了便于部署,建议使用static

对于我们提供的静态文件资源,可以通过http://127.0.0.1/static/html/index.html来访问。而且在index.html中引用的静态资源文件,我们给定的路径也符合/static/...的格式,故页面可以正常浏览。

<link href="/static/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/plugins/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="/static/css/reset.css" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet">
<link href="/static/css/index.css" rel="stylesheet"><script src="/static/js/jquery.min.js"></script>
<script src="/static/plugins/bootstrap/js/bootstrap.min.js"></script>
<script src="/static/js/index.js"></script>

StaticFileHandler

我们再看刚刚访问页面时使用的路径http://127.0.0.1/static/html/index.html,这中url显然对用户是不友好的,访问很不方便。我们可以通过tornado.web.StaticFileHandler来自由映射静态文件与其访问路径url。

tornado.web.StaticFileHandler是tornado预置的用来提供静态资源文件的handler。

# -*- coding: utf-8 -*-
# __auther__ = 'lewen'import os
import tornado.web
import tornado.ioloop
import tornado.httpserverfrom tornado.web import RequestHandler, url, StaticFileHandler
from tornado.options import options, definedefine("port", default=8000, type=int, help="run the server on the port")class IndexHandler(RequestHandler):def get(self, *args, **kwargs):passif __name__ == "__main__":tornado.options.parse_command_line()current_path = os.path.dirname(__file__)app = tornado.web.Application([(r'/(.*)', StaticFileHandler,{"path": os.path.join(current_path, "static/html"), "default_filename": "index.html"}),# (r'^/view/(.*)$', StaticFileHandler, {"path": os.path.join(current_path, "static/html")}),
    ],debug=True,# static_path=os.path.join(os.path.dirname(__file__), "static"),
)http_server = tornado.httpserver.HTTPServer(app)http_server.listen(options.port)tornado.ioloop.IOLoop.current().start()
path 用来指明提供静态文件的根路径,并在此目录中寻找在路由中用正则表达式提取的文件名。
default_filename 用来指定访问路由中未指明文件名时,默认提供的文件。

现在,对于静态文件statics/html/index.html,可以通过三种方式进行访问:

  1. http://127.0.0.1/static/html/index.html
  2. http://127.0.0.1/
  3. http://127.0.0.1/view/index.html

statics 静态文件夹跟http://127.0.0.1:8000/static/html/index.html# 中的static(默认访问路径) 不一样

访问http://127.0.0.1:8000/static 时tornado会转换去对应的设置文件夹去找

部署时,将静态文件放到 nginx 上为了方便查找及引用,改为 static


4.2 使用模板

1. 路径与渲染

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

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

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

现在我们将静态文件目录statics/html中的index.html复制一份到templates目录中,此时文件目录结构为:

.
├── statics
│   ├── css
│   │   ├── index.css
│   │   ├── main.css
│   │   └── reset.css
│   ├── html
│   │   └── index.html
│   ├── images
│   │   ├── home01.jpg
│   │   ├── home02.jpg
│   │   ├── home03.jpg
│   │   └── landlord01.jpg
│   ├── js
│   │   ├── index.js
│   │   └── jquery.min.js
│   └── plugins
│       ├── bootstrap
│       │   └─...
│       └── font-awesome
│           └─...
├── templates
│   └── index.html
└── test.py

View Code

在handler中使用render()方法来渲染模板并返回给客户端。

class IndexHandler(RequestHandler):def get(self):self.render("index.html") # 渲染主页模板,并返回给客户端。
current_path = os.path.dirname(__file__)
app = tornado.web.Application([(r'^/$', IndexHandler),(r'^/view/(.*)$', StaticFileHandler, {"path":os.path.join(current_path, "statics/html")}),],static_path=os.path.join(current_path, "statics"),template_path=os.path.join(os.path.dirname(__file__), "templates"),
)

2. 模板语法

2-1 变量与表达式

在tornado的模板中使用{{}}作为变量或表达式的占位符,使用render渲染后占位符{{}}会被替换为相应的结果值。

我们将index.html中的一条房源信息记录

<li class="house-item"><a href=""><img src="/static/images/home01.jpg"></a><div class="house-desc"><div class="landlord-pic"><img src="/static/images/landlord01.jpg"></div><div class="house-price">¥<span>398</span>/晚</div><div class="house-intro"><span class="house-title">宽窄巷子+160平大空间+文化保护区双地铁</span><em>整套出租 - 5分/6点评 - 北京市丰台区六里桥地铁</em></div></div>
</li>
改为模板:
<li class="house-item"><a href=""><img src="/static/images/home01.jpg"></a><div class="house-desc"><div class="landlord-pic"><img src="/static/images/landlord01.jpg"></div><div class="house-price">¥<span>{{price}}</span>/晚</div><div class="house-intro"><span class="house-title">{{title}}</span><em>整套出租 - {{score}}分/{{comments}}点评 - {{position}}</em></div></div>
</li>

渲染方式如下:
class IndexHandler(RequestHandler):def get(self):house_info = {"price": 398,"title": "宽窄巷子+160平大空间+文化保护区双地铁","score": 5,"comments": 6,"position": "北京市丰台区六里桥地铁"}self.render("index.html", **house_info)

{{ }}不仅可以包含变量,还可以是表达式,可以加减,如:

<li class="house-item"><a href=""><img src="/static/images/home01.jpg"></a><div class="house-desc"><div class="landlord-pic"><img src="/static/images/landlord01.jpg"></div><div class="house-price">¥<span>{{p1 + p2}}</span>/晚</div><div class="house-intro"><span class="house-title">{{"+".join(titles)}}</span><em>整套出租 - {{score}}分/{{comments}}点评 - {{position}}</em></div></div>
</li>
class IndexHandler(RequestHandler):def get(self):house_info = {"p1": 198,"p2": 200,"titles": ["宽窄巷子", "160平大空间", "文化保护区双地铁"],"score": 5,"comments": 6,"position": "北京市丰台区六里桥地铁"}self.render("index.html", **house_info)

2-2 控制语句

可以在Tornado模板中使用Python条件和循环语句。控制语句以{%和%}包围,并以类似下面的形式被使用:{% if page is None %}
或{% if len(entries) == 3 %}
控制语句的大部分就像对应的Python语句一样工作,支持if、for、while,注意end:{% if ... %} ... {% elif ... %} ... {% else ... %} ... {% end %}
{% for ... in ... %} ... {% end %}
{% while ... %} ... {% end %}

再次修改index.html:

<ul class="house-list">{% if len(houses) > 0 %}{% for house in houses %}<li class="house-item"><a href=""><img src="/static/images/home01.jpg"></a><div class="house-desc"><div class="landlord-pic"><img src="/static/images/landlord01.jpg"></div><div class="house-price">¥<span>{{house["price"]}}</span>/晚</div><div class="house-intro"><span class="house-title">{{house["title"]}}</span><em>整套出租 - {{house["score"]}}分/{{house["comments"]}}点评 - {{house["position"]}}</em></div></div></li>{% end %}{% else %}对不起,暂时没有房源。{% end %}
</ul>

View Code

python中渲染语句为:

class IndexHandler(RequestHandler):def get(self):houses = [{"price": 398,"title": "宽窄巷子+160平大空间+文化保护区双地铁","score": 5,"comments": 6,"position": "北京市丰台区六里桥地铁"},{"price": 398,"title": "宽窄巷子+160平大空间+文化保护区双地铁","score": 5,"comments": 6,"position": "北京市丰台区六里桥地铁"},{"price": 398,"title": "宽窄巷子+160平大空间+文化保护区双地铁","score": 5,"comments": 6,"position": "北京市丰台区六里桥地铁"},{"price": 398,"title": "宽窄巷子+160平大空间+文化保护区双地铁","score": 5,"comments": 6,"position": "北京市丰台区六里桥地铁"},{"price": 398,"title": "宽窄巷子+160平大空间+文化保护区双地铁","score": 5,"comments": 6,"position": "北京市丰台区六里桥地铁"}]self.render("index.html", houses=houses)

View Code

2-3 函数

static_url()

Tornado模板模块提供了一个叫作static_url的函数来生成静态文件目录下文件的URL。如下面的示例代码:

<link rel="stylesheet" href="{{ static_url("style.css") }}"> 

这个对static_url的调用生成了URL的值,并渲染输出类似下面的代码:

<link rel="stylesheet" href="/static/style.css?v=ab12"> 

优点:

  • static_url函数创建了一个基于文件内容的hash值,并将其添加到URL末尾(查询字符串的参数v)。这个hash值确保浏览器总是加载一个文件的最新版而不是之前的缓存版本。无论是在你应用的开发阶段,还是在部署到生产环境使用时,都非常有用,因为你的用户不必再为了看到你的静态内容而清除浏览器缓存了。
  • 另一个好处是你可以改变你应用URL的结构,而不需要改变模板中的代码。例如,可以通过设置static_url_prefix来更改Tornado的默认静态路径前缀/static。如果使用static_url而不是硬编码的话,代码不需要改变。

转义

我们新建一个表单页面new.html<!DOCTYPE html>
<html><head><title>新建房源</title></head><body><form method="post"><textarea name="text"></textarea><input type="submit" value="提交"></form>{{text}}</body>
</html>

对应的handler为:class NewHandler(RequestHandler):def get(self):self.render("new.html", text="")def post(self):text = self.get_argument("text", "") print textself.render("new.html", text=text)
当我们在表单中填入如下内容时:<script>alert("hello!");</script>

写入的js程序并没有运行,而是显示出来了:

我们查看页面源代码,发现<、>、"等被转换为对应的html字符。

&lt;script&gt;alert(&quot;hello!&quot;);&lt;/script&gt;

这是因为tornado中默认开启了模板自动转义功能,防止网站受到恶意攻击。

我们可以通过raw语句来输出不被转义的原始格式,如:

{% raw text %}

注意:在Firefox浏览器中会直接弹出alert窗口,而在Chrome浏览器中,需要set_header("X-XSS-Protection", 0)

若要关闭自动转义,一种方法是在Application构造函数中传递autoescape=None,另一种方法是在每页模板中修改自动转义行为,添加如下语句:

{% autoescape None %}

escape()

关闭自动转义后,可以使用escape()函数来对特定变量进行转义,如:

{{ escape(text) }}

自定义函数

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

我们修改后端如下:

def house_title_join(titles):return "+".join(titles)class IndexHandler(RequestHandler):def get(self):house_list = [{"price": 398,"titles": ["宽窄巷子", "160平大空间", "文化保护区双地铁"],"score": 5,"comments": 6,"position": "北京市丰台区六里桥地铁"},{"price": 398,"titles": ["宽窄巷子", "160平大空间", "文化保护区双地铁"],"score": 5,"comments": 6,"position": "北京市丰台区六里桥地铁"}]self.render("index.html", houses=house_list, title_join = house_title_join)

前段模板我们修改为:

<ul class="house-list">{% if len(houses) > 0 %}{% for house in houses %}<li class="house-item"><a href=""><img src="/static/images/home01.jpg"></a><div class="house-desc"><div class="landlord-pic"><img src="/static/images/landlord01.jpg"></div><div class="house-price">¥<span>{{house["price"]}}</span>/晚</div><div class="house-intro"><span class="house-title">{{title_join(house["titles"])}}</span><em>整套出租 - {{house["score"]}}分/{{house["comments"]}}点评 - {{house["position"]}}</em></div></div></li>{% end %}{% else %}对不起,暂时没有房源。{% end %}
</ul>

View Code

2-4 块

我们可以使用块来复用模板,块语法如下:

{% block block_name %} {% end %}

现在,我们对模板index.html进行抽象,抽离出父模板base.html如下:

<!DOCTYPE html>
<html>
<head> <meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">{% block page_title %}{% end %}<link href="{{static_url('plugins/bootstrap/css/bootstrap.min.css')}}" rel="stylesheet"><link href="{{static_url('plugins/font-awesome/css/font-awesome.min.css')}}" rel="stylesheet"><link href="{{static_url('css/reset.css')}}" rel="stylesheet"><link href="{{static_url('css/main.css')}}" rel="stylesheet">{% block css_files %}{% end %}
</head>
<body><div class="container"><div class="top-bar">{% block header %}{% end %}</div>{% block body %}{% end %}<div class="footer">{% block footer %}{% end %}</div></div><script src="{{static_url('js/jquery.min.js')}}"></script><script src="{{static_url('plugins/bootstrap/js/bootstrap.min.js')}}"></script>{% block js_files %}{% end %}
</body>
</html>

View Code

而子模板index.html使用extends来使用父模板base.html,如下:

{% extends "base.html" %}{% block page_title %}<title>爱家-房源</title>
{% end %}{% block css_files %}<link href="{{static_url('css/index.css')}}" rel="stylesheet">
{% end %} {% block js_files %}<script src="{{static_url('js/index.js')}}"></script>
{% end %}{% block header %}<div class="nav-bar"><h3 class="page-title">房 源</h3></div>
{% end %}{% block body %}<ul class="house-list">{% if len(houses) > 0 %}{% for house in houses %}<li class="house-item"><a href=""><img src="/static/images/home01.jpg"></a><div class="house-desc"><div class="landlord-pic"><img src="/static/images/landlord01.jpg"></div><div class="house-price">¥<span>{{house["price"]}}</span>/晚</div><div class="house-intro"><span class="house-title">{{title_join(house["titles"])}}</span><em>整套出租 - {{house["score"]}}分/{{house["comments"]}}点评 - {{house["position"]}}</em></div></div></li>{% end %}{% else %}对不起,暂时没有房源。{% end %}</ul>
{% end %}{% block footer %}<p><span><i class="fa fa-copyright"></i></span>爱家租房&nbsp;&nbsp;享受家的温馨</p>
{% end %}

View Code


转载于:https://www.cnblogs.com/wenyule/articles/10354635.html

t4 tornado 模板相关推荐

  1. T4文本模板转换过程

    T4文本模板转换过程将文本模板文件作为输入,生成一个新的文本文件作为输出. 例如,可以使用文本模板生成 Visual Basic 或 C# 代码,还可以生成 HTML 报告. 有三个组件参与这一过程: ...

  2. Python学习笔记——Tornado模板

    4.1 静态文件 现在有一个预先写好的静态页面文件 (下载静态文件资源), 我们来看下如何用tornado提供静态文件. static_path 我们可以通过向web.Application类的构造函 ...

  3. tornado模板引擎原理

    前言 老师问小明:已经a=1, 求a+1的值. 小明挠挠头,思考后回答:老师,a+1的结果是2. 以上是一个非常简单的例子,实际上就是一个模板编译过程. a=1,表示一个命名空间(namespace) ...

  4. tornado 模板

    使用模板 render 在 application 中配置模板文件和静态文件的路径: template_path='templates',static_path='static', templates ...

  5. Tornado使用mako 模板总结

    2019独角兽企业重金招聘Python工程师标准>>> import tornado.web import tornado.ioloop import tornado.auth im ...

  6. 第四篇:白话tornado源码之褪去模板外衣的前戏

    加班程序员最辛苦,来张图醒醒脑吧! ... ... ... 好了,醒醒吧,回归现实看代码了!! 执行字符串表示的函数,并为该函数提供全局变量 本篇的内容从题目中就可以看出来,就是为之后剖析tornad ...

  7. 你必须懂的 T4 模板:深入浅出

    示例代码:示例代码__你必须懂的T4模板:浅入深出.rar (一)什么是T4模板? T4,即4个T开头的英文字母组合:Text Template Transformation Toolkit. T4文 ...

  8. .NET中关于T4模板的使用

    文章目录 介绍 简单说下什么是t4模版 具体使用方式 TransformText方法 自定义T4模板引擎 两种方式的比较 总结 介绍 最近工作中需要按一定的模板模型生成指定的文件,虽然可以直接拼接字符 ...

  9. tornado总结4-html模板使用2

    2019独角兽企业重金招聘Python工程师标准>>> 参考地址 http://www.tornadoweb.org/en/stable/guide/templates.html?h ...

最新文章

  1. autohotkey快捷键
  2. 同洲EOC局端MAC地址修改方法
  3. VTK:PolyData之ExtractSelection
  4. 飞畅科技-工业以太网的应用现状及前景展望
  5. 360——新式的流氓
  6. 0927_C/C++笔试题_10:16道c语言面试例子【2】
  7. 坐标下降法和交替最小二乘法的区别是什么?
  8. 交换机在局域网内的日常工作
  9. SAPAS91导入期初固定资产数据往年购置与当年购置的区别
  10. Java 反射机制:(三)类的加载
  11. jquery日历插件daterangepicker全面详解汇总
  12. HDU CCPC网络选拔赛 6441 Find Integer(数学)
  13. 简单版的相似图片搜索原理
  14. 【独行秀才】macOS Monterey 12.2.1正式版(21D62)原版镜像
  15. html期末作业代码网页设计——化妆品电商网站(4页) HTML+CSS+JavaScript 使用html+css实现一个静态页面(含源码)
  16. AppScan使用教程
  17. 快递公司泄露买家信息最高罚3万 快递员双挨罚
  18. 职业规划之ABZ,未雨绸缪35岁危机
  19. 【Lifelong learning】Achieving Forgetting Prevention and Knowledge Transfer in Continual Learning
  20. MT5 Gateway API 行情与交易流通性完成

热门文章

  1. JavaScript算法(实例六)输出日期 / 数组合并 / 小球下落--反弹运动
  2. mysql 1.42_MySQL索引(一)
  3. android程序表白,几条曲线构建Android表白程序
  4. 基于链表的两个集合的差集
  5. android profiler 简书,(四)Android 性能优化 Energy Profiler
  6. C语言手写自定义三维数组
  7. linux网卡IP同一网段,Linux下多网卡不同IP在同一网段的情况
  8. Redis 开发与运维
  9. php 编辑config.php配置文件
  10. linux 中 svn 服务器搭建 重启