前言:我们在浏览网页的时候,有时候会发现页面上顶部和底部,都是一样的,那这些是在每个页面上都要再写一次吗?
这就涉及到我们今天要说的模板继承来达到这种效果!
模板继承
{% block name%}...{% end %}
不同的内容,在父模板中用block块,在子模板用引用对应block块,进行重写覆盖父模板中的,如果子模板没有引用block,则直接继承模板中的。
{% extend filename %}
继承模板,在子模板中会把父模板的所有内容都继承到子模板中,减少大量重复代码。
父模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}父模板{% end %}</title>
<style>
* {
margin: 0;
padding: 0;
}
#oTop{
width: 100%;
background: #000;
color: #fff;
text-align: center;
padding: 10px 0;
position: fixed;
left: 0;
top: 0;
}
#oBottom {
width: 100%;
background: #000;
color: #fff;
text-align: center;
padding: 20px 0;
position: fixed;
left: 0;
bottom: 0;
}
#oMid{
width: 90%;
margin: 50px auto; /*由于同级元素固定定位,导致这个相对于父级定位*/
border: 1px solid #ccc;
text-align: center;
}
{% block css %}{% end %} /*不同的用block块包起来*/
</style>
</head>
<body>
<header id="oTop">顶部</header>
<div id="oMid">
{% block content %}
中间区域!
{% end %}
</div>
<footer id="oBottom">底部</footer>
</body>
</html>
效果:子模板继承
<!--继承模板,在子模板中会把父模板的所有内容都继承到子模板中,减少大量重复代码 -->
{% extends base.html %}
<!-- 被词语句包裹的代码块在子模板中可以被重写,覆盖父模板中的-->
{% block title %}子模板继承{% end %} <!--继承的时候,如果子模板写了对应block块,则会替换父模板继承的内容,若没写,则直接从父模板继承过来-->
{% block css %}{% end %}
{% block content %}
首页--中间区域
{% end %}
效果:
总结:
- 当页面继承其他页面之后,需要实现相应的块才有作用,在块外面的代码是没有作用的。
- extend 可以继承父模板,从而节省了大量重复代码,同时也为修改带来了极大的方便,但是需要注意的是一定只能单继承,一个模板只能继承一个模板。
模板导入
为解决一个模板只能继承一个模板问题,可以通过模板导入来解决。
{% include filename%}
include 可以导入一些其他的模板文件,一般使用 include 的时候,导入的模板中不要再出现 extend 和 block
被导入的模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>菜单导航</title>
<style>
* {
margin: 0;
padding: 0;
}
ul{
text-decoration: none;
margin: 10% 1%;
width: 10%;
}
li{
background: #000;
text-align: center;
margin-top: 2px;
padding: 5px 10px;
color: #fff;
}
</style>
</head>
<body>
<div>
<ul>
<li>菜单一</li>
<li>菜单二</li>
<li>菜单三</li>
<li>菜单四</li>
</ul>
</div>
</body>
</html>
导入模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}父模板{% end %}</title>
<style>
* {
margin: 0;
padding: 0;
}
#oTop{
width: 100%;
background: #000;
color: #fff;
text-align: center;
padding: 10px 0;
position: fixed;
left: 0;
top: 0;
}
#oBottom {
width: 100%;
background: #000;
color: #fff;
text-align: center;
padding: 20px 0;
position: fixed;
left: 0;
bottom: 0;
}
#oMid{
width: 90%;
margin: 50px auto; /*由于同级元素固定定位,导致这个相对于父级定位*/
border: 1px solid #ccc;
text-align: center;
}
{% block css %}{% end %} /*不同的用block块包起来*/
</style>
</head>
<body>
<header id="oTop">顶部</header>
<div id="oMid">
{% block content %}
中间区域!
{% end %}
{% include ./navmenu.html %}
</div>
<footer id="oBottom">底部</footer>
</body>
</html>
在父模板中可以include,在子模板中也可以include,不过还是依然需要写在block块中。include 可以导入模板文件,但是导入的模板中不要再出现 extend 和 block。
函数和类的导入
渲染时导入
在 Handler 中渲染模板时传入
class Cal:
def sum(self,x,y):
return x+y
class IndexHander(tornado.web.RequestHandler):
def test(self):
return '测试函数导入...'
def get(self):
self.render('index.html',
test = self.test,#在 Handler 中渲染模板时传入方法
Cal = Cal #传入类
)
在对应index.html中可以直接通过标签获取
{{test()}}
<br/>
{{Cal().sum(3,8)}}
模板中直接导入
在模板中也可以直接导入 python 模块。
<br/>
{% import time %} <!-- 导入内置模块 -->
{{time.time()}}
<br/>
{% from util.modify import mul %} <!-- 注意:python解释器查找 mod_file 时是根据 py 文件的路径来查找的,不是根据模板的路径来查找-->
{{mul(6,6)}}
全部代码:
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define,options
define('port', default= 8080, help='run port', type=int)
class Cal:
def sum(self,x,y):
return x+y
class IndexHander(tornado.web.RequestHandler):
def test(self):
return '测试函数导入...'
def get(self):
self.render('index.html',
test = self.test,#在 Handler 中渲染模板时传入方法
Cal = Cal #传入类 )
application = tornado.web.Application(
handlers=[
(r'/', IndexHander)
],
template_path='templates',
debug=True
)
if __name__ == '__main__':
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
html代码:
<!--继承模板,在子模板中会把父模板的所有内容都继承到子模板中,减少大量重复代码 -->
{% extends base.html %}
<!-- 被词语句包裹的代码块在子模板中可以被重写,覆盖父模板中的-->
{% block title %}子模板继承{% end %} <!--继承的时候,如果子模板写了对应block块,则会替换父模板继承的内容,若没写,则直接从父模板继承过来-->
{% block css %}{% end %}
{% block content %}
首页--中间区域
<br/>
{{test()}}
<br/>
{{Cal().sum(3,8)}}
<br/>
{% import time %} <!-- 导入内置模块 -->
{{time.time()}}
<br/>
{% from util.modify import mul %} <!-- 注意:python解释器查找 mod_file 时是根据 py 文件的路径来查找的,不是根据模板的路径来查找-->
{{mul(6,6)}}
{% end %}
ui_methods和ui_modules
上面提到了传入函数和类的两种办法,如果一个函数或类需要在很多模板中被导入那之前的两种方式会不会很繁琐呢?
下面来处理这种问题:
- 第一步:ui_methods.py
新建文件ui_methods.py ,这里的文件名是随意的只要在import时合法即可,这里可以新建一个文件夹,如util,来放置 ui_methods.py 和 ui_modules.py
def method1(self): #注意这里要加上self
return 'ui_methods 1'
def method1(self):
return 'ui_methods 2'
- 第二步:ui_modules.py
新建文件ui_modules.py,使用ui_modules需要继承UIModule类
from tornado.web import UIModule
class UiModule(UIModule):
def render(self, *args, **kwargs):
return '这是ui_module'
- 第三步:在项目中导入
import util.ui_methods
import util.ui_modules
- 第四步:配置 Application 参数
application = tornado.web.Application(
handlers=[
(r'/', IndexHander)
],
template_path='templates',
ui_methods=util.ui_methods,
ui_modules=util.ui_modules,
#也可以写成字典形式
# ui_modules={'UiModule':util.ui_modules.UiModule},
debug=True
)
- 第五步:在模板中调用
<br/>
{{method1()}}
<br/>
{% module UiModule() %}
演示案例,部分代码:
class Advertisement(UIModule):
def render(self, *args, **kwargs):
return self.render_string('06ad.html')
def css_files(self): #引入css
return "/static/css/King_Chance_Layer7.css"
def javascript_files(self): #引入js
return [
"/static/js/jquery_1_7.js",
"/static/js/King_Chance_Layer.js",
"/static/js/King_layer_test.js",
]
模板其他命令
apply
使用apply语句,使用函数的作用范围到最近的{%end%}为止
{% apply upper %}
python
菜鸟ing
{% end %}
<br/>
{{upper('python 菜鸟 ing')}}
linkify
linkify生成一个链接,但是要注意模板转义。
{{linkify('百度:www.baidu.com')}}
<br/>
{% raw linkify('百度:www.baidu.com') %}