python模板渲染jinja2 - pythonweb(3)
Jinja2是一个快速、表达式化的可扩展模板引擎,他由werkzueg作者Armin Ronacher(习惯人们称他为 mitsuhiko) 开发,用于pythonweb html页面的数据渲染,和java-servlet的jsp平齐。jinja2使得能够在页面中使用python语法,被翻译成为html页面;jinja2还有一个作用是能够渲染word模板用于合同签属等实际应用。
3.1 基本语法:
注意所有控制结构都必须以{% end关键字%} 结束。
- 变量取值 {{ pythonic_code }}
- 控制结构 {% pythonic_code %}
- 模板注释 {# pythonic_ocde #}
3.2 模板渲染:
模板中的路径都是与初始化模板的根路径相对的,由此来加载html文件位置,用字典数据渲染html页面。假设config.py文件与templates目录平齐:
from jinja2 import Environment
from jinja2 import FileSystemLoader
# 配置jinja模板
template_path = os.path.join(os.path.dirname(__file__), "templates")
jinja_env = Environment(
loader=FileSystemLoader(template_path), autoescape=True
)
def save(dst, data):
with open(dst, 'w') as fp:
fp.write(data)
# 渲染模板,与werkzueg结合可以返回一个Response
# 这个例子将渲染好的html页面输出到文件out.html
def render_template(template_name, **context):
t = jinja_env.get_template(template_name)
# t.render(context) 返回一个str字符串
data = t.render(context)
save('./out.html', data)
3.3 jinja2控制结构:
必须保证python语法的正确性,否则模板渲染就会报错
(1) 选择结构:
a) 数据:
session = {"user": {"id": 1, "name": "test1"}}
render_template("test_if.html", sessionScope=session)
b) 模板:
<!--test_if.html-->
{# 两分支选择示例, 多分支同python #}
<ul>
{% if sessionScope.get("user", False) %}
<li>个人中心 accout</li>
<li>注销 logout</li>
{% else %}
<li>登录 login</li>
<li>注册 register</li>
{% endif %}
</ul>
(2) 循环结构:
a) 数据:
goods_lst = [
{"id":1 , "name": "test_for1"},
{"id":2 , "name": "test_for2"}
]
render_template("test_for.html", goodslist=goods_lst)
b) 模板:
<!-- test_for.html -->
<table>
{% for goods in goodslist %}
{# 大可不必要这个if, 说明用法 #}
{% if loop.first %}
<tr>
<th>ID</th>
<th>Name</th>
</tr>
{% endif %}
<tr>
{# 对象可以点去, 字典关键字键取 #}
<td>{{ goods.id }}</td>
<td>{{ goods.name }}</td>
</tr>
{% endfor %}
</table>
jinja2 的特殊循环变量:
变量 | 描述 |
---|---|
loop.index / loop.index0 | 当前迭代的索引, 默认从1开始(index0 从0开始) |
loop.revindex / loop.revindex0 | 逆向迭代索引, 范围 [len , 1] / [len-1, 0] |
loop.first / loop.last | 布尔值, 是否时迭代的开始 / 结束 |
loop.lenth | 迭代列表长度 |
3.4 jinja2过滤器
通过context传递的数据字典,在jinja2的模板语言中只支持get 、keys、 values、 items iterkeys、itervalues、iteritems、
__getitem__、__contain__ 这些python方法, 后面两个分别是点取和in关键字;如果要在模板变量取值时进行一些操作就需要借助函数,就是模板提供的过滤器选项,如果要避免这些操作,就需要在python代码对数据进行预处理。
(1) 模板内置过滤器:
类型 | 函数名称 | 功能 |
---|---|---|
字符串 | safe capitalize / title lower / upper reverse striptags truncate | 禁用转义 首字母大写 / 单词首字母大写 转小写 / 转大写 字符串反转 删掉HTML标签 字符串截断 |
列表 | first last length sum sort | 取第一个元素 取最后一个元素 取列表长度 列表求合 列表排序(大可不必这里面做) |
数值 | int / round |
(2) 过滤器调用:
一般模板语法{% filter %} ,也可以在模板取值时管道操作,管道支持链式操作:
{# 块语法 #}
{% filter upper%}
edg niubi
{% endfilter %}
{# 管道取 #}
{{ edg niubi | title | reverse }}
(3) 自定义过滤器:
jinja2支持将自定义python函数传入jinja2环境中,可供调用,这些情况一般可以提前处理避免:
def multiple(a, b):
return a * b
# 注册自定义过滤器
jinja_env['multi'] = multiple
# 模板调用
# {{ 3 | multi:2 }}
3.5 模板复用与继承:
对于一个大型网站来说,网站的主题结构都是一样的,jinja2支持模板的复用,可以使各功能模块的html页面更加注重于自己本身的功能,模板语法使用block关键字来预留需要填充的内容,使用extend关键字来继承基础模板的html代码。
(1) 基础模板:
<!-- front/basic.html -->
<html>
<head>
<!-- 预留标题填充-->
<title>{% block title_head %} {% endblock %}</title>
<link href="xxxx.css" rel="stylesheet"/>
<script type="text/javascript" src="xxx.js"></script>
</head>
<body>
<header>
This is header!
</header>
<!-- 预留主体内容填充-->
{% block main_body %}
{% endblock %}
</body>
</html>
(2) 模板填充:
<!-- front/login.html -->
{% extends 'front/basic.html' %}
{% block title_head %} 登录页面 {% endblock %}
<!-- 填充3)中的内容 -->
{% block main_body %}
<main>
登录功能页面
</main>
{% endblock %}
(3) 特定页面的样式及功能:
直接填充head标签, 使用super关键字继承原有内容,定义自己的style和js:
{% block head %}
{{ super() }} # 用于获取原有的信息
<style type='text/css'>
.important { color: #FFFFFF }
</style>
<script>
console.log("This is Login Page");
</script>
{% endblock %}
有关与pythonweb模板渲染的相关基础的内容就介绍完了,jinja2还可以与docxtpl结合,用于生成word模板,十分实用;关于控制层werkzueg, 数据层 python db-api就已经全部介绍完了,下一篇一个类似于SpringMVC的实例来综合这些内容。