当我们有多个模板的时候,很多模板之间其实相似度很高。我们期望可以重用部分网页代码。这在tornado中可以通过extends语句来实现。为了扩展一个已经存在的模板,你只需要在新的模板文件的顶部放上一句{% extends "filename.html" %}。比如,为了在新模板中扩展一个父模板(在这里假设为之前我们使用过的index.html),你可以这样使用:{% extends "index.html" %}
这就使得新文件继承index.html的所有标签,并且覆写为期望的内容。
新添加一个indexHandler_temp类来返回index1.html
class indexHandler_temp(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
return self.render(‘index1.html‘)
index1.html中的代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index1</title>
</head>
<body>
{% extends "index.html" %}
</body>
</html>
当我们访问http://127.0.0.1/index1的时候得到的页面会和index中的页面是一模一样的。
在这里通过extends完全继承了父页面,但是实际子页面和父页面还是有很多差别的。我们需要在子页面上定义很多自己的东西,这里就需要用到block语句,在index页面中添加如下的描述:
{% block info %}<p>父页面</p>{% end %}
然后在index1页面中添加,这里重写了block info的信息。
{% block info %}
<p>index1重写block info</p>
{% end %}
得到的页面显示如下,可以看到block info中的信息为“index1重写block info”, 覆盖了父页面的描述。
当然还可以在block中引用变量
{% block info %}
<p>{{ info }}</p>
{% end %}
在对应的代码中传递该变量的值就可以了
class indexHandler_temp(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
return self.render(‘index1.html‘,info="information of index1
UI模板:
UI模块是封装模板中包含的标记、样式以及行为的可复用组件。它所定义的元素通常用于多个模板交叉复用或在同一个模板中重复使用。模块本身是一个继承自Tornado的UIModule类的简单Python类,并定义了一个render方法。当一个模板使用{% module Foo(...) %}标签引用一个模块时,Tornado的模板引擎调用模块的render方法,然后返回一个字符串来替换模板中的模块标签。UI模块也可以在渲染后的页面中嵌入自己的JavaScript和CSS文件,或指定额外包含的JavaScript或CSS文件。你可以定义可选的embedded_javascript、embedded_css、javascript_files和css_files方法来实现这一方法。
来看下如何使用,首先定义一个HelloModule继承自tornado.web.UIModule
class HelloModule(tornado.web.UIModule):
def render(self, *args, **kwargs):
return ‘<h1>hello world</h1>‘
在Application中添加ui_module的赋值:ui_modules={‘hello‘:HelloModule}
在index1中使用{% module hello() %}。此时运行,index1会显示hello world
在来看下更高级的应用,在ui module中传递参数。
第一步:首先在indexHandler_temp中添加books的定义,在一个列表中包含一个字典。
class indexHandler_temp(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
return self.render(‘index1.html‘,books=[
{
"title":"Programming Collective Intelligence",
"subtitle": "Building Smart Web 2.0 Applications",
"image":"/static/images/collective_intelligence.gif",
"author": "Toby Segaran",
"date_added":1310248056,
"date_released": "August 2007",
"isbn":"978-0-596-52932-1",
"description":"<p>This fascinating book demonstrates how you "
"can build web applications to mine the enormous amount of data created by people "
"on the Internet. With the sophisticated algorithms in this book, you can write "
"smart programs to access interesting datasets from other web sites, collect data "
"from users of your own applications, and analyze and understand the data once "
"you‘ve found it.</p>"
},])
然后修改HelloModule的定义,在这里返回采用self.render_string的函数。并且返回temp.html页面,并传递参数book
class HelloModule(tornado.web.UIModule):
def render(self, book):
return self.render_string(‘temp.html‘,book=book)
下面来看下index1.html页面的代码:
{% for book in books %}
{% module Book(book) %}
{% end %}
temp.html页面的代码:
<div class="book">
<h3 class="book_title">{{ book["title"] }}</h3>
{% if book["subtitle"] != "" %}
<h4 class="book_subtitle">{{ book["subtitle"] }}</h4>
{% end %}
<div class="book_details">
<div class="book_date_released">Released: {{ book["date_released"]}}</div>
<div class="book_date_added">
Added: {{ locale.format_date(book["date_added"], relative=False) }}
</div>
<h5>Description:</h5>
<div class="book_body">{% raw book["description"] %}</div>
</div>
</div>
当访问index1页面的时候,结果如下:
下面来介绍下运行机制:
1 在index1中遍历books并对每个遍历到的字典调用Book(book)
2 此时调用HelloModule,传入字典book。并通过在temp.html中实现呈现代码
3 在temp.html中写HTML代码,呈现字典中的信息。
通过这种方法,可以将books的呈现方式抽象出来,只要其他页面想调用的时候,只需要调用Book这个模块就可以了。不用每个页面都去实现遍历实现。