您的位置:首页 > 编程语言 > Python开发

边做边学Python Flask Web开发(5)-- 使用Jinjia2模板(中)

2016-07-06 15:41 656 查看
上一篇介绍了Jinjia2模板系统的基本用法,本篇将深入对Jinjia2进行探讨,对网页设计中经常会用到的一些高级特性进行介绍。

模板复用

复用是网页设计非常常用的特性,比如我们的页面头部的网站名称和页尾的版权标识通常都是一样的,我们的菜单有时候在每个页面也都是一样的。作为一名程序员,重复做同样的事情是完全不可接受的。在Jinjia2中,通常可以使用继承、包含和宏三种特性来完成模板的利用。

继承

这和类的继承没有什么分别,因此也就有了父模板和子模板的概念。例如,我们可以把包含HTML框架、页头、页尾的模板页做为父模板,其它的子模板只需要继承它,就自动拥有了头部和尾部。

下面是一个父模板的例子:

<html>
<head>
{% block head %}
<title>{% block title %}Base Title{% endblock %} - My Application</title>
{% endblock %}
</head>
<body>
<h1>This Header is inherited from base.html</h1>
{% block body %}     {% endblock %}
<hr/>
This footer is inherited from base.html
</body>
</html>


现在我们在templates目录新建一个文件,写下一行代码,保存为child.html

{% extends "base.html" %}


在创建了Flask app的源代码中加上一个路由/child,完整的代码如下:

import json,pprint,sys
from flask import Flask,render_template
app = Flask(__name__)

@app.route('/child')
def child1():
return render_template("child.html")

if __name__ == '__main__':
app.run(debug=True)


运行这个程序我们看到如下的结果:



注意红色标记的部分,这个页面的title仍然是Base Title,原因是我们在子模板中并没有对{% block title %}进行改写。将child.html扩充:

{% extends "base.html" %}
{% block title %} Child1 {% endblock %}
{% block body %}<h2> This is body of child1 </h2> {% endblock %}


再看看页面的标题已被替换,body部分也被充实了内容。



模板继承中,可以使用一个特殊的super函数,将父模板内容块中定义的内容附加到子模板中,这有点像Python类的super函数。

{% block title%}
Child1 -
{{ super() }}
{% endblock %}


大家可以动手试一下这样写的话页面的标题会变成什么样子。

包含

可以使用include将一个独立的模板文件包含进来,这一点和PHP非常相似。我们继续修改child.html:

{% extends "base.html" %}
{% block title %} Child1 {% endblock %}
{% include 'menu.html' %}
{% block body %}<h2> This is body of child1 </h2> {% endblock %}


同时,新建一个名称是menu.html的模板文件,放置在同一目录下,内容如下:

<hr/>
<ul>
<li>Menu Item 1</li>
<li>Menu Item 2</li>
<li>Menu Item 3</li>
<hr/>


现在的页面已经包含了一个菜单项。



最后我们介绍一下宏。宏的概念和大家了解的Office中的宏很类似,它通常用来做一些需要多次处理的简单工作。Jinjia2中定义和使用宏有点像定义和使用函数,下面继续我们的child.html,在里面添加上宏的定义和调用代码。

<!--这里先定义宏-->
{% macro render_comment(comment) %}
<li>MACRO:{{ comment }}</li>
{% endmacro %}
<!--定义结束-->
<!--调用宏-->
<ul>
{% for comment in comments %}
{{ render_comment(comment) }}
{% endfor %}
</ul>
<!--调用结束-->


我们还可以把宏代码放置在一个单独的文件中,下面我们新建一个文件macros.html,内容如下:

{% macro render_comment_from_file(comment) %}
<li>来自文件:{{ comment }}</li>
{% endmacro %}


从文件中载入宏代码用到了一个新的命令import,继续修改child.html,增加以下内容

<h4>这是由从文件导入的宏生成的</h4>
{% import 'macros.html' as macros %}
<ul>
{% for comment in comments %}
{{ macros.render_comment_from_file(comment) }}
{% endfor %}
</ul>


至此,完整的child.html文件如下:

{% extends "base.html" %}
{% block title %} Child1 {% endblock %}
{% include 'menu.html' %}
{% block body %}
<h2> This is body of child1 </h2>
<!--这里先定义宏--> {% macro render_comment(comment) %} <li>MACRO:{{ comment }}</li> {% endmacro %} <!--定义结束--> <!--调用宏--> <ul> {% for comment in comments %} {{ render_comment(comment) }} {% endfor %} </ul> <!--调用结束-->
<h4>这是由从文件导入的宏生成的</h4> {% import 'macros.html' as macros %} <ul> {% for comment in comments %} {{ macros.render_comment_from_file(comment) }} {% endfor %} </ul>
{% endblock %}


格式化

前几章中我们了解到,Jinjia2的工作模式是向模板发送数据再渲染成HTML页面。不过在很多情况下,发送到页面的数据并不是我们期望的格式,这时候就要用到它的格式化功能。

Jinjia2中的格式化操作最常见的是使用过滤器进行的。

字符串

我们用一个例子对字符串的格式化操作进行说明,将下面的代码保存为strings.html

<h1>Hello {{user}}</h1>
<hr />
<p>转为首字母大写: Hello, {{ user|capitalize }}</p>
<p>转为大写: Hello, {{ user|upper }}</p>
<p>转为小写: Hello, {{ user|lower }}</p>
<p>转为标题样式(每个主题词首字母大写): Hello, {{ user|title }}</p>
<p>去掉首尾空格(页面上无效果): Hello, {{ user|trim }}</p>
<p>默认的HTML过滤操作: {{ myhtmlstr }}</p>
<p>添加safe过滤器(有安全隐患,如果不能确认字符串是安全的请不要使用!): {{ myhtmlstr|safe }}</p>
<p>过滤掉HTML标记: {{ myhtmlstr|striptags }}</p>
<hr />


在创建了Flask app的源代码中加上一个路由/strings,完整的代码如下:

import json,pprint,sys
from flask import Flask,render_template
app = Flask(__name__)

@app.route('/strings')
def strings():
return render_template("strings.html",user="ivan wang",
myhtmlstr="<strong>this is <i>emphasized</i></strong>")

if __name__ == '__main__':
app.run(debug=True)


该页面在浏览器中显示如下



数字

仍然使用一个例子来演示数字的格式化方法,将下面的代码保存为numerics.html:

<h2>和数字相关的过滤器</h2>
<p>四舍五入:{{n1|round}}</p>
<p>保留3位小数并四舍五入:{{n1|round(3)}}</p>
<p>保留1位小数下取整:{{n1|round(1,'floor')}}</p>
<p>保留1位小数上取整:{{n1|round(1,'ceil')}}</p>
<p>取整:{{n1|int}}</p>
<p>使用格式化字符串:{{"%.2f" % n1}}</p>
<p>使用string.format函数进行千分位显示:{{"{:,}".format(n2)}}</p>
<p>使用string.format函数对多个数字进行格式化:{{"Number1:{0:.2%}, Number2:{1:,}".format(n1,n2)}}</p>


在python代码中添加一个numerics路由:

@app.route('/numerics')
def numerics():
return render_template("numerics.html",n1=3.14159,n2=29838721)


页面显示如下:



在Jinja2中使用格式化字符串和String.format为数字和字符的格式化输出带来了无限的可能,更多的信息请参考 https://docs.python.org/2/library/string.html#format-string-syntax

自定义

Jinja2内置了功能丰富的过滤器,可以参考[[]]http://jinja.pocoo.org/docs/dev/templates]]获取更多的信息。

如果所有内置的过滤器都不能满足要求,Jinja2还允许你创建自定义的过滤器。

添加一个userdefined路由,代码如下:

@app.template_filter('reverse')
def reverse_filter(s):
return s[::-1]

@app.route('/userdefined')
def userdefined():
return render_template("userdefined.html",s="abcdefg")


userdefined.html内容如下:

{{s|reverse}}


请大家自行尝试该模板的渲染结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息