Flask学习总结笔记(4)-- Jinja2模板引擎之二

Jinja2模板引擎官方文档详细介绍了其中的API函数、沙箱、模板设计文档等,这里主要就一些常用的知识点进行总结。

0x01 模板基础

常见的几种模板语句如下:

{%...%}     #运行Jinja2的语句;
{{…}}       #在页面中打印Jinja2运行的结果
{#...#}     #注释

看下面的例子:

(1)views.py

from flask import render_template

@app.route('/index')
def index():
    return render_template('index1.html',
                           name='kikay',
                           age=20)

(2)templates文件夹下新建模板index1.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test</title>
</head>
<body>
<p>测试</p>
<p>直接输出姓名:{{name}}</p>
{#这是注释:判断是否存在age#}
{%if age%}
<p>年龄:{{age}}</p>
{%else%}
<p>不存在年龄</p>
{%endif%}
</body>
</html>

输出效果:

如果想输入原始的Jinja2语句,而不是作为特殊字符进行解析,可以包含在{%raw%}…{%%endraw}中:
views.py

@app.route('/raw')
def raw():
    return render_template('raw.html',name='kikay')

raw.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Raw</title>
</head>
<body>
<div>
    <p>姓名:{{name}}</p>
    {%raw%}
    <p>转义姓名:{{name}}</p>
    {%endraw%}
</div>
</body>
</html>

效果如下:

上面的例子都需要调用render_template('*.html',var_key=***)来渲染模板。其中的函数render_template是把Jinja2模板引擎集成到程序中。Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。

0x02 控制语句

添加一些控制语句,index2.html如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
<div>
    {%if author%}
    <h1>Hello,{{author}}</h1>
    {%else%}
    <h1>Nobody</h1>
    {%endif%}
</div>
</body>
</html>

views.py:

@app.route('/index2')
def index2():
    author='kikay'
    return render_template('index2.html',
                           author=author)

输出:

注释掉author:

@app.route('/index2')
def index2():
    author='kikay'
    return render_template('index2.html')
                           #author=author)

效果如下:

当参数不存在时,Jinja2模板在渲染时直接忽略掉。更复杂一些,现在还要输出作者好友的列表。

index3.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Firends</title>
</head>
<body>
<div>
    <h1>作者:{{author.name}}</h1>
    <table>
        <thread>
            <th>姓名</th>
            <th>年龄</th>
        </thread>
        {%for f in author.friends%}
        <tr>
            <td>{{f.name}}</td>
            <td>{{f.age}}</td>
        </tr>
        {%endfor%}
    </table>

</div>
</body>
</html>

views.py:

@app.route('/index3')
def index3():
    author={
        'name':'kikay',
        'age':20,
        'friends':[
            {'name':'Andy','age':60},
            {'name':'Tom','age':29},
            {'name':u'小花','age':18}
        ]
    }
    return render_template('index3.html',
                           author=author)

效果如下:

这里需要指出的是,输出带有中文时,注意编码的问题。类似于Python中函数的定义,Jinja2模板引擎中的macro关键字可以看成是一个函数的定义:

{%macro showinfo(info)%}
这是{{info}}!!!<br />
{%endmacro%}
{%for info in infos%}
{{showinfo(info)}}
{%endfor%}

0x03 模板继承

随着应用的拓展,我们可能在多个页面中使用了相同的HTML代码,并且需要每一个页面都同步,和其他模板引擎一样,Jinja2也支持模板继承。我们在templates下新建一个layout_base.html文件,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {%if title%}
    <title>{{title}}</title>
    {%else%}
    <title>No title</title>
    {%endif%}
    <!--一引入js文件-->
    {%block script%}
    <script src="test.js"></script>
    {%endblock%}
</head>
<body>
<div>
    {%block t1%}{%endblock%}
    <p>----------模板分隔符------------</p>
    {%block t2%}{%endblock%}
</div>
</body>
</html>

里面有3个block标签,这是为继承该模板的html模板替换使用的。新建index4.html继承layout_base.html:

{%extends 'layout_base.html'%}
{%block script%}
{{super()}}
<script src="test2.js"></script>
{%endblock%}

{%block t1%}
{%if author%}
<h1>Hello,{{author.name}}</h1>
{%else%}
<h1>Nobody</h1>
{%endif%}
{%endblock%}

{%block t2%}
<table>
    <thread>
        <th>姓名</th>
        <th>年龄</th>
    </thread>
    {%for f in author.friends%}
    <tr>
        <td>{{f.name}}</td>
        <td>{{f.age}}</td>
    </tr>
    {%endfor%}
</table>
{%endblock%}

效果如下:

extends指明该模板是从哪个模板继承而来的。上面例子中的{{super()}},因为模板中其中包含的内容不是空的,所以需要用{{super()}}来获取原来的内容。如果一个html中包含1个以上的extends标签就会报错,即最多继承于1个模板。

0x04 模板设计

Flask集成了Bootstrap包,可以使用Flask-Bootstrap来渲染模板,首先需要安装(利用pip):

pip install flask-bootstrap

具体过程参见以前的博客(Flask学习总结笔记(1)– 环境配置)。

__init__.py中初始化Flask-Bootstrap:

from flask.ext.bootstrap import Bootstrap

修改后的完整__init__.py如下:

#!flask/bin/env python
#coding:utf-8

__author__ = 'kikay'

from flask import Flask
from flask.ext.bootstrap import Bootstrap

#定义app对象
app=Flask(__name__)
#定义Bootstrap对象
bootstrap=Bootstrap(app)

from app import views

完成Flask-Bootstrap初始化后,就可以在程序中使用一个包含全部Bootstrap文件的基模板。这个模板利用Jinja2的模板继承机制,让程序扩展一个具有基本页面结构的基模板,其中就有用来引入 Bootstrap 的元素。(官方教程),关于Bootstrap的内容可以参看我的博客(Bootstrap学习总结笔记)。

下面是实现一个导航样式的例子:

bootstrap.html

<!--引入Flask-Bootstrap中的基模板-->
{%extends 'bootstrap/base.html'%}

<!--添加html属性-->
{%block html_attribs%}lang="zh-cn"{%endblock%}

<!--添加metas标签-->
{%block metas%}
    {{super()}}
    <meta charset="UTF-8">
{%endblock%}

<!--添加网页的样式-->
{%block styles%}
    {{super()}}
    <link rel="stylesheet" href="{{url_for('.static',filename='css/block.css')}}">
{%endblock%}

{%block scripts%}
    {{super()}}
    <script src="{{url_for('.static',filename='js/block.js')}}"></script>
{%endblock%}

<!--网页标题-->
{%block title%}Flask-Bootstrap{%endblock%}

<!--网页导航-->
{%block navbar%}
<div class="container">
    <nav class="navbar navbar-inverse">
        <div class="navbar-header">
            <button type="button" class="btn btn-default navbar-toggle" data-toggle="collapse" data-target="#navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a href="#" class="navbar-brand">网站标题</a>
        </div>
        <div class="collapse navbar-collapse" id="navbar">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">首 页</a></li>
                <li><a href="#">新闻</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                        下拉菜单
                        <span class="caret"></span>
                    </a>
                    <ul class="dropdown-menu">
                        <li><a href="#">菜单1</a></li>
                        <li><a href="#">菜单2</a></li>
                        <li><a href="#">菜单3</a></li>
                    </ul>
                </li>
            </ul>
            <form class="nav navbar-form navbar-right">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="用户名">
                </div>
                <div class="form-group">
                    <input type="password" class="form-control" placeholder="密码">
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary form-control">提 交</button>
                </div>
            </form>
        </div>
    </nav>
</div>
{%endblock%}

<!--网页正文-->
{%block content%}
<div class="container">
    <div class="page-header">
        {%if author%}
        <h1>Hello,{{author.name}}</h1>
        {%else%}
        <h1>Nobody</h1>
        {%endif%}
    </div>
    <div class="col-center-block">
        <!--展示朋友列表-->
        {%if author.friends%}
        <table class="table table-bordered table-striped table-hover table-condensed">
            <thead class="alert-danger">
                <th>姓名</th>
                <th>年龄</th>
            </thead>
            {%for f in author.friends%}
            <tr class="alert-success">
                <td>{{f.name}}</td>
                <td>{{f.age}}</td>
            </tr>
            {%endfor%}
        </table>
        {%endif%}
    </div>
</div>
<script>
</script>
{%endblock%}

views.py:

@app.route('/bootstrap')
def bootstrap():
    author={
        'name':'kikay',
        'age':20,
        'friends':[
            {'name':'Andy','age':60},
            {'name':'Tom','age':29},
            {'name':u'小花','age':18}
        ]
    }
    return render_template('bootstrap.html',
                           author=author,
                           title='Bootstrap')

效果如下:

看下源代码,可以更好理解这种渲染的效果。

<!--引入Flask-Bootstrap中的基模板-->
<!DOCTYPE html>
<htmllang="zh-cn">
  <head>
    <title>Flask-Bootstrap</title>

    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta charset="UTF-8">


    <!-- Bootstrap -->
    <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="/static/css/block.css">

  </head>
  <body>

<div class="container">
    <nav class="navbar navbar-inverse">
        <div class="navbar-header">
            <button type="button" class="btn btn-default navbar-toggle" data-toggle="collapse" data-target="#navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a href="#" class="navbar-brand">网站标题</a>
        </div>
        <div class="collapse navbar-collapse" id="navbar">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">首 页</a></li>
                <li><a href="#">新闻</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                        下拉菜单
                        <span class="caret"></span>
                    </a>
                    <ul class="dropdown-menu">
                        <li><a href="#">菜单1</a></li>
                        <li><a href="#">菜单2</a></li>
                        <li><a href="#">菜单3</a></li>
                    </ul>
                </li>
            </ul>
            <form class="nav navbar-form navbar-right">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="用户名">
                </div>
                <div class="form-group">
                    <input type="password" class="form-control" placeholder="密码">
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary form-control">提 交</button>
                </div>
            </form>
        </div>
    </nav>
</div>


<div class="container">
    <div class="page-header">

        <h1>Hello,kikay</h1>

    </div>
    <div class="col-center-block">
        <!--展示朋友列表-->

        <table class="table table-bordered table-striped table-hover table-condensed">
            <thead class="alert-danger">
                <th>姓名</th>
                <th>年龄</th>
            </thead>

            <tr class="alert-success">
                <td>Andy</td>
                <td>60</td>
            </tr>

            <tr class="alert-success">
                <td>Tom</td>
                <td>29</td>
            </tr>

            <tr class="alert-success">
                <td>小花</td>
                <td>18</td>
            </tr>

        </table>

    </div>
</div>
<script>
</script>




    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="/static/js/block.js"></script>

  </body>
</html>

在Flask-Bootstrap中,支持的block样式如下表:

这里不再一一介绍,在实际应用中可以自己体会。另外上面用到了url_for函数做路由的映射,具体使用可以参见我前面的博客(Flask学习总结笔记(2)– Hello world程序)中关于构造Url的内容。这里引入了js和css文件,对应的文件结构如下:

关于Flask-Jinja2模板引擎的使用问题就讲到这里,以后在实际使用过程中,再慢慢总结与领会。

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值