Python 模板 Jinja2

模板

要了解Jinja2,就需要先理解模板的概念。模板在Python的web开发中广泛使用,它能够有效的将业务逻辑和页面逻辑分开,使代码可读性更强、更加容易理解和维护。模板简单来说就是一个包含占位变量表示动态部分的文件,模板文件在经过动态赋值后,返回给用户(可理解为渲染)。Python中自带一个简单的模板,就是string提供的:

>>> import string
>>> temp = string.Template("$who is $role")
>>> temp.substitute(who="red hat", role="Linux")
'red hat is Linux'
>>> temp.substitute(who="opensource", role="software")
'opensource is software'
>>>

Python自带的模板功能极其有限,如果我们要在模板中使用控制语句、表达式和继承等功能的话,就无法实现。目前主流的模板系统,最常见的就是Jinja2和mako。

Jinja2

Jinja2是Flask作者开发的一个模板系统,起初是仿Django模板的一个模板系统,为Flask提供模板支持,由于其灵活性、快速和安全等优点呗广泛使用,其优点有:

  • 相对于Template,Jinja2更加灵活,它提供了控制结构、表达式和继承等;
  • 相对于Mako,Jinja2仅有控制结构,不允许在模板中编写太多业务逻辑;
  • 相对于Django模板,Jinja2性能更好;
  • Jinja2模板可读性很棒;

安装Jinja2

由于Jinja2属于第三方包,首先需要对其进行安装:

pip install jinja2

测试Jinja2是否安装成功:

python -c "import jinja2"

# 必须使用双引号"",没有报错就表示安装成功

Jinja2语法

作为一个模板系统,它还提供了特殊的语法,我们按照它支持地语法进行编写之后,就能使用Jinja2模板进行渲染。

1.基本语法

  • 控制结构:{% %};
  • 变量取值: {{ }};
  • 注释{# #};

简单jinja2例子:

{# This is jinja2 code
{% for file in filenames %}
...
{% endfor %}
#}

可以看到,for循环的使用方式和Python比较类似,但是没有句尾的冒号,另外需要使用endfor作为结尾,其实在jinja2中,if也是一样的,结尾需要使用endif。

2.Jinja2变量

Jinja2模板中使用{{ }}语法表示一个变量,它是一种特殊的占位符。当利用Jinja2进行渲染时,它会把这些特殊的占位符进行填充/替换,Jinja2支持Python中所有的Python数据类型,比如:列表、字符串、对象等;

<p>this is a directory: {{ mydict["key"] }}</p>
<p>this is a list: {{ mylist[2] }}</p>
<p>this is a object: {{ myobject.something }}</p>

3.Jinja2中的过滤器

变量可以通过过滤器进行修改,过滤器可以理解为是Jinja2里面的内置函数和字符串处理函数。常用的过滤器有:

过滤器名称 说明
safe 渲染时值不转义
capitalize 把值得首字母转成大写,其他字母转成小写
lower 把值转换成小写形式
upper 把值转换成大写形式
title 把值中每个单词的首字母都转换成大写
trim 把值得首尾空格去掉
striptags 渲染之前把值中所有的HTML标签都删掉
join 拼接多个值为字符串
replace 替换字符串的值
round 默认对数字进行四舍五入,也可用参数进行控制
int 把值转换成整形

如何使用这些过滤器呢?只需要在变量后面使用管道(|)分割,多个过滤器可以链式调用,前一个过滤器的输出会作为后一个过滤器得输入。

{{ 'abc' | captialize  }}
# Abc {{ 'abc' | upper }}
# ABC {{ 'hello world' | title }}
# Hello World {{ "hello world" | replace('world','daxin') | upper }}
# HELLO DAXIN {{ 18.18 | round | int }}
# 18

4.Jinja2的控制结构

Jinja2中的if语句类似于Python的if语句,它也具有但分支、多分支等多种结构,不同的是,条件语句不需要使用冒号结尾,而结束控制语句,需要使用endif关键字。

{% if daxin.safe %}
daxin is safe.
{% elif daxin.dead %}
daxin is dead
{% else %}
daxin is okay
{% endif %}

5.Jinja2的for循环

Jinja2中的for循环用于迭代Python的数据类型,包括列表、元组和字典,在Jinja2中不存在while循环:

# 迭代列表
<ul>
{% for user in users %}
<li>{{ user.username|title }}</li>
{% endfor %}
</ul>
# 迭代字典
<dl>
{% for key, value in my_dict.iteritems() %}
<dt>{{ key }}</dt>
<dd>{{ value}}</dd>
{% endfor %}
</dl>

当然也可以加入else语句,在循环正确执行完毕后执行。在for循环中,Jinja2还提供了一些特殊变量,用来获取当前的遍历状态:

变量 描述
loop.index 当前迭代的索引(从1开始)
loop.index0 当前迭代的索引(从0开始)
loop.first 是否是第一次迭代,返回bool
loop.last 是否是最后一次迭代,返回bool
loop.length 序列中的项目数量
loop.revindex 到循环结束的次数(从1开始)
loop.revindex0 到循环结束的次数(从0开始)

6.Jinja2的宏

宏类似于Python中的函数,我们在宏中定义行为,还可以进行传递参数,就像Python中的函数一样。在宏中定义一个宏的关键字是macro,后面跟其宏的名称和参数等:

{% macro input(name,age=18) %}   # 参数age的默认值为18

 <input type='text' name="{{ name }}" value="{{ age }}" >

{% endmacro %}

调用方法也和Python的类似:

<p>{{ input('daxin') }} </p>
<p>{{ input('daxin',age=20) }} </p>

7.Jinja2的继承和Super函数

Jinja2中最强大的部分就是模板继承,模板继承允许我们创建一个基本(骨架)文件,其他文件从该骨架文件继承,然后针对自己需要的地方进行修改。Jinja2的骨架文件中,利用block关键字表示其包含的内容可以进行修改,以下面的骨架文件base.html为例:

<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="style.css"/>
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
<script>This is javascript code </script>
{% endblock %}
</div>
</body>
</html>

这里定义了四处block,即:head、title、content、footer,那么如何进行继承和变量替换呢?注意看下面的文件:

{% extend "base.html" %}       # 继承base.html文件

{% block title %} Dachenzi {% endblock %}   # 定制title部分的内容

{% block head %}
{{ super() }} # 用于获取原有的信息
<style type='text/css'>
.important { color: #FFFFFF }
</style>
{% endblock %} # 其他不修改的原封不同的继承

注:super()函数表示获取block块中定义的原来的内容

利用Jinja2进行渲染

Jinja2模块中有一个名为Environment的类,这个类的实例用于存储配置和全局对象,然后从文件系统或其他位置中加载模板。

1.基本使用方法

大多数应用都在初始化的时候遇见一个Environment对象,并用它加载模板。Environment支持两种加载方式:

  • PackageLoader:包加载器
  • FileSystemLoader:文件系统加载器

2.PackageLoader

使用包加载器来加载文档的最简单方式如下:

from jinja2 import PackageLoader,Environment
env = Environment(loader=PackageLoader('python_project','templates')) # 创建一个包加载器对象 template = env.get_template('bast.html') # 获取一个模板文件
template.render(name='daxin',age=18) # 渲染

注意:

  • PackageLoader()两个参数为:Python包的名称、模板目录名称;
  • get_template():获取模板目录下的某个具体文件;
  • render():接收变量,对模板进行渲染;

3.FileSystemLoader

文件加载器,不需要模板文件存在某个Python包下,可以直接访问系统中的文件。

最新文章

  1. Gym - 101102C
  2. eclipse通过JDBC连接数据库不成功
  3. Linux简介及常用命令使用1--linux环境搭建
  4. perl文件句柄的传递
  5. Qt5程序参数包含中文GBK编码的问题
  6. jquery选择器之内容选择器
  7. Selenium2+python自动化21-TXT数据参数化
  8. 迅为三星Exynos 4412开发板四核Cortex-A9ARM安卓linux开发板
  9. 2016-1-6第一个完整APP 私人通讯录的实现 4:编辑联系人
  10. 解决eclipse下pydev的unresolved import的问题
  11. Spring配置概述
  12. Oracle中获取执行计划的几种方法分析
  13. hadoop 2.2.0 编译报错: [ERROR] class file for org.mortbay.component.AbstractLifeCycle not found
  14. 如何编写一个JSON解析器
  15. jvm参数解析(含调优过程)
  16. 为fastdfs文件服务器新增一个storage
  17. LINUX服务器搭建和常用配置介绍
  18. Script to Collect Log File Sync Diagnostic Information (lfsdiag.sql) (文档 ID 1064487.1)
  19. delphi CopyFileProgressBar 拷贝文件显示进度条
  20. 【转】PowerDesigner快捷键

热门文章

  1. vagrant boxes
  2. 考研编程练习---StringMatching(后缀表达式)
  3. (三)SpringBoot2.0基础篇- 持久层,jdbcTemplate和JpaRespository
  4. 一个很easy的脚本--php获取服务器端的相关信息
  5. Google Chrome插件分享
  6. centos 6.5 双网卡 上网 virtualbox nat hostonly
  7. 从零开始的Python学习Episode 8——深浅拷贝
  8. leetcode13_C++罗马数字转整数
  9. 5个最优秀的微信小程序UI组件库
  10. &lt;力荐&gt;非常好的正则表达式的详解&lt;力荐&gt;