1. 路径与渲染

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

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

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

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

在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>

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)

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>

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>

而子模板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 %}

11 Tornado - 使用模板相关推荐

  1. Tornado之模板

    知识点 静态文件配置 static_path StaticFileHandler 模板使用 变量与表达式 控制语句 函数 块 4.1 静态文件 现在有一个预先写好的静态页面文件 (下载静态文件资源), ...

  2. 第三波:HTML+CSS+JavaScript数据可视化大屏平台模板实例11大通用模板,面向各行各业。

    第三波:HTML+CSS+JavaScript数据可视化大屏平台模板实例11大通用模板,面向各行各业. HTML+CSS+JS数据可视化大屏平台模板实例21-大数据可视化通用模板 HTML+CSS+J ...

  3. C++11可变数量模板参数可变类型模板参数并使用lamada函数调用使用范例

    为了完成这个功能,耗费一整天. 背景是需要到一张表中查询,条件不一样,但是都可以通过PreparedStatement_setXX设置,想体验一把C++11的高级模板特性,设计如下封装 inline ...

  4. web框架详解之 tornado 四 模板引擎、session、验证码、xss

    一.模板引擎 基本使用继承,extends 页面整体布局用继承导入,include 如果是小组件等重复的那么就用导入 下面是目录 首先在controllers里面创建一个文件,文件里面是页面类 #/u ...

  5. Python3 --- Tornado之模板

    目录 一.模板渲染 二.模板语法 2.1.变量输出 2.2.表达式输出 2.3.注释一个部分,防止他被输出 2.4.模板替换 2.5.模板继承 2.6.for循环 2.7.from引入包 2.8.im ...

  6. c++基础学习(11)--(模板、预处理器、信号处理)

    文章目录 目录 1.模板 2.预处理器 3.信号处理 目录 1.模板 模板是泛型编程的基础,泛型编程:以一种独立于任何特定类型的方式 #include <iostream> #includ ...

  7. C++11线程库模板

    推荐一个非常好的C++11的线程库模板:https://github.com/progschj/ThreadPool/blob/master/ThreadPool.h 包含了C++11的特性,重点学习 ...

  8. C++11 学习笔记 模板的细节(右尖括号,using,函数模板默认参数)

    一.模板的右尖括号 在C++98/03的泛型编程中,模板实例化有一个很繁琐的地方,就是连续两个右尖括号(>>)会被编译解释成右移操作符,而不是模板参数表的形式.即 <span sty ...

  9. C++11特性(模板类 initializer_list)

    [1]initializer_list模板类 C++primer 原文如下: 通读原文相关篇幅,分析解读内容如下: 提供initializer_list类的初衷,为了便于将有限个同一类型(或可转换为同 ...

最新文章

  1. 机器学习数据预处理之缺失值:预测填充(回归模型填充、分类模型填充)
  2. python函数名的语法_Python 基础语法六 ——函数
  3. 教你在Linux下构建主、从域名服务器!
  4. 使用emu8086学习汇编 int 21h 指令
  5. Okhttp3-网络请求流程解析
  6. 【DevOps+LIVE】直播复盘 – DevOps能力成长模型2018首发
  7. 厉害了!顶级学术期刊封面的“中国元素”
  8. python模拟抛体运动_换个姿势学物理!用Python和Matplotlib进行模拟
  9. 蔡高厅高等数学18-函数在一点处的连续、函数在区间内的连续、两类间断点的判断
  10. MATLAB常用求导和求偏导函数
  11. JAVA反射————基础版
  12. 毕业论文ppt的研究方法及过程计算机专业,毕业论文答辩ppt(要求和制作技巧)...
  13. 微软掷豪金投资海底数据电缆
  14. html+ul隐藏滚动条,2种方法实现CSS隐藏滚动条并可以滚动内容的方法
  15. 设计模式(3)----- 简单工厂模式
  16. 【初等概率论】 04
  17. 华为矿鸿操作系统横空出世,煤矿智能化开启新篇章
  18. Docsify 创建文档网站
  19. 代码表白小特效 一个比一个浪漫 !!!快收藏!!
  20. centos7 挂载fat32格式的u盘和ntfs格式的移动硬盘

热门文章

  1. 形式语言与自动机理论(1)----基础介绍
  2. mac 删除Provisioning Profiles(描述文件)
  3. str[i] 数字强制转int型
  4. Spring bean的自动装配
  5. echarts 常见的功能点小结
  6. 百度竞价最低CPC出价策略
  7. 一年省下1000亿? 原来零售玩的是闷声发大财
  8. 体验心灵与阿根太湖电缆吹音频质量
  9. Apache 与 php的配置
  10. 使用Python实现RSA加密算法及详解RSA算法