Tornado模板继承和UImodul 和 UImethods

前言:我们在浏览网页的时候,有时候会发现页面上顶部和底部,都是一样的,那这些是在每个页面上都要再写一次吗?
这就涉及到我们今天要说的模板继承来达到这种效果!

模板继承

{% 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>

效果:
image.png

子模板继承

<!--继承模板,在子模板中会把父模板的所有内容都继承到子模板中,减少大量重复代码 -->
{% extends base.html %}

<!-- 被词语句包裹的代码块在子模板中可以被重写,覆盖父模板中的-->
{% block title %}子模板继承{% end %} <!--继承的时候,如果子模板写了对应block块,则会替换父模板继承的内容,若没写,则直接从父模板继承过来-->


{% block css %}{% end %}

{% block content %}
    首页--中间区域
{% end %}

效果:


image.png

总结:

  1. 当页面继承其他页面之后,需要实现相应的块才有作用,在块外面的代码是没有作用的。
  2. 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>
image.png

在父模板中可以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 %}
image.png

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() %}
image.png

演示案例,部分代码:

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')}}
image.png
linkify

linkify生成一个链接,但是要注意模板转义。

{{linkify('百度:www.baidu.com')}}
<br/>
{% raw linkify('百度:www.baidu.com') %}
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容