{% raw %}
Python Jinja 教程
Jinja 教程展示了如何使用 Jinja 模块在 Python 中创建模板。
Python Jinja 模块
Jinja 是 Python 的模板引擎。 它类似于 Django 模板引擎。
模板引擎或模板处理器是一个旨在将模板与数据模型结合以生成文档的库。 模板引擎通常用于在源代码预处理中生成大量电子邮件,或生成动态 HTML 页面。
我们创建一个模板引擎,在其中定义静态零件和动态零件。 动态部分随后将替换为数据。 渲染功能随后将模板与数据结合在一起。
Jinja 安装
$ sudo pip3 install jinja2
我们使用pip3
工具安装 Jinja。
Jinja 分隔符
Jinja 在模板字符串中使用各种分隔符。
{% %}
- 陈述{{ }}
- 要打印到模板输出的表达式{# #}
- 模板输出中未包含的注释# ##
- 行语句
Jinja 简单的例子
在第一个示例中,我们创建一个非常简单的模板。
simple.py
#!/usr/bin/env python3
from jinja2 import Template
name = input("Enter your name: ")
tm = Template("Hello {{ name }}")
msg = tm.render(name=name)
print(msg)
该示例要求输入用户名并生成消息字符串,该消息字符串将打印给用户。 模板引擎类似于 Python format()
方法; 但是模板引擎功能更强大,并且具有更多功能。
from jinja2 import Template
我们从jinja2
模块导入Template
对象。 Template
是中央模板对象。 它代表一个已编译的模板,并用于对其进行求值。
tm = Template("Hello {{ name }}")
在我们的模板中,我们具有用于打印变量的{{ }}
语法。 变量以render()
方法传递。
msg = tm.render(name=name)
使用render()
方法,我们生成最终输出。 该方法将模板字符串与作为参数传递的数据连接在一起。 传递给render()
方法的变量称为上下文变量。
$ ./simple.py
Enter your name: Paul
Hello Paul
这是一个示例输出。
在下一个示例中,我们使用两个变量。
simple2.py
#!/usr/bin/env python3
from jinja2 import Template
name = 'Peter'
age = 34
tm = Template("My name is {{ name }} and I am {{ age }}")
msg = tm.render(name=name, age=age)
print(msg)
模板字符串呈现两个变量:名称和年龄。 这次变量是硬编码的。
$ ./simple2.py
My name is Peter and I am 34
这是输出。
Jinja 对象
我们可以使用模板字符串中的对象。
objects.py
#!/usr/bin/env python3
from jinja2 import Template
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def getAge(self):
return self.age
def getName(self):
return self.name
person = Person('Peter', 34)
tm = Template("My name is {{ per.getName() }} and I am {{ per.getAge() }}")
msg = tm.render(per=person)
print(msg)
在示例中,我们定义了Person
对象。 我们通过两个获取器获取名称和年龄。
字典
Jinja 允许使用方便的点表示法来访问 Python 字典中的数据。
dicts.py
#!/usr/bin/env python3
from jinja2 import Template
person = { 'name': 'Person', 'age': 34 }
tm = Template("My name is {{ per.name }} and I am {{ per.age }}")
# tm = Template("My name is {{ per['name'] }} and I am {{ per['age'] }}")
msg = tm.render(per=person)
print(msg)
我们有一本人字典。 我们使用点运算符访问字典键。
tm = Template("My name is {{ per.name }} and I am {{ per.age }}")
# tm = Template("My name is {{ per['name'] }} and I am {{ per['age'] }}")
活动方式和注释方式均有效。 点符号更方便。
Jinja 原始数据
我们可以使用raw
和endraw
标记转义 Jinja 分隔符。
raw_data.py
#!/usr/bin/env python3
from jinja2 import Template
data = '''
{% raw %}
His name is {{ name }}
{% endraw %}
'''
tm = Template(data)
msg = tm.render(name='Peter')
print(msg)
通过使用raw
和endraw
块,我们逃避了 Jinja {{ }}
语法。 它是按字面意思印刷的。
Jinja 转义数据
为了转义诸如<
或>
字符之类的数据,我们可以使用过滤器或escape()
函数。
escape_data.py
#!/usr/bin/env python3
from jinja2 import Template, escape
data = '<a>Today is a sunny day</a>'
tm = Template("{{ data | e}}")
msg = tm.render(data=data)
print(msg)
print(escape(data))
该示例转义<
和>
字符。
tm = Template("{{ data | e}}")
使用e
过滤器,可以转储数据。 过滤器应用|
字符。
print(escape(data))
转义函数执行相同的操作。
Jinja 表达式
for 表达式用于迭代模板中的数据收集。
现在,我们不再使用简单的字符串模板。 我们使用一个FileSystemLoader
加载的文本文件。
for_expr.py
#!/usr/bin/env python3
from jinja2 import Environment, FileSystemLoader
persons = [
{'name': 'Andrej', 'age': 34},
{'name': 'Mark', 'age': 17},
{'name': 'Thomas', 'age': 44},
{'name': 'Lucy', 'age': 14},
{'name': 'Robert', 'age': 23},
{'name': 'Dragomir', 'age': 54}
]
file_loader = FileSystemLoader('templates')
env = Environment(loader=file_loader)
template = env.get_template('showpersons.txt')
output = template.render(persons=persons)
print(output)
在此示例中,模板是showpersons.txt
文件。 该文件位于templates
目录中。
persons = [
{'name': 'Andrej', 'age': 34},
{'name': 'Mark', 'age': 17},
{'name': 'Thomas', 'age': 44},
{'name': 'Lucy', 'age': 14},
{'name': 'Robert', 'age': 23},
{'name': 'Dragomir', 'age': 54}
]
数据是字典列表。
file_loader = FileSystemLoader('templates')
env = Environment(loader=file_loader)
我们定义一个FileSystemLoader
。 从templates
目录中检索模板。
template = env.get_template('showpersons.txt')
我们使用get_template()
方法获得模板。
templates/showpersons.txt
{% for person in persons -%}
{{ person.name }} {{ person.age }}
{% endfor %}
在模板文件中,我们使用for
表达式遍历集合。 我们显示此人的姓名和年龄。 %
字符旁边的破折号用于控制空格。
Jinja 条件
条件是满足特定条件时要求值的表达式。
conditionals.py
#!/usr/bin/env python3
from jinja2 import Environment, FileSystemLoader
persons = [
{'name': 'Andrej', 'age': 34},
{'name': 'Mark', 'age': 17},
{'name': 'Thomas', 'age': 44},
{'name': 'Lucy', 'age': 14},
{'name': 'Robert', 'age': 23},
{'name': 'Dragomir', 'age': 54},
]
file_loader = FileSystemLoader('templates')
env = Environment(loader=file_loader)
env.trim_blocks = True
env.lstrip_blocks = True
env.rstrip_blocks = True
template = env.get_template('showminors.txt')
output = template.render(persons=persons)
print(output)
该示例仅打印未成年人。 未成年人是指未满 18 岁的人。
env.trim_blocks = True
env.lstrip_blocks = True
env.rstrip_blocks = True
输出中的空白可以通过环境属性来控制。
templates/showminors.txt
{% for person in persons %}
{% if person.age < 18 %}
{{- person.name }}
{% endif %}
{%- endfor %}
在模板中,我们仅使用if
表达式输出 18 岁以下的人。
$ ./conditionals.py
Mark
Lucy
这是输出。
Jinja sum
过滤器
可以将过滤器应用于数据以对其进行修改。 例如,sum
过滤器可以对数据求和,escape
过滤器对它们进行转义,sort
过滤器对它们进行排序。
sum_filter.py
#!/usr/bin/env python3
from jinja2 import Environment, FileSystemLoader
cars = [
{'name': 'Audi', 'price': 23000},
{'name': 'Skoda', 'price': 17300},
{'name': 'Volvo', 'price': 44300},
{'name': 'Volkswagen', 'price': 21300}
]
file_loader = FileSystemLoader('templates')
env = Environment(loader=file_loader)
template = env.get_template('sumprices.txt')
output = template.render(cars=cars)
print(output)
在示例中,我们使用sum
过滤器来计算所有汽车价格的总和。
cars = [
{'name': 'Audi', 'price': 23000},
{'name': 'Skoda', 'price': 17300},
{'name': 'Volvo', 'price': 44300},
{'name': 'Volkswagen', 'price': 21300}
]
我们有汽车字典的列表。 每个字典都有一个价格键。 它将用于计算总和。
templates/sumprices.txt
The sum of car prices is {{ cars | sum(attribute='price') }}
在模板文件中,我们将过滤器应用于汽车集合对象。 根据price
属性计算总和。
$ ./sum_filter.py
The sum of car prices is 105900
这是输出。
Jinja 模板继承
模板继承是一项强大的功能,可减少代码重复并改善代码组织。 我们定义了一个基本模板,其他模板文件也从中继承。 这些模板文件将覆盖基本模板文件的特定块。
ineritance.py
#!/usr/bin/env python3
from jinja2 import Environment, FileSystemLoader
content = 'This is about page'
file_loader = FileSystemLoader('templates')
env = Environment(loader=file_loader)
template = env.get_template('about.html')
output = template.render(content=content)
print(output)
我们渲染about.html
文件。 它继承自base.html
文件。
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content%}
{% endblock %}
</body>
</html>
在base.html
文件中,我们声明两个块:标题和内容。 这些块将在子模板中填充特定的标签和文本。
about.html
{% extends 'base.html' %}
{% block title%}About page{% endblock %}
{% block content %}
<h1>About page</h1>
<p>
This is about page
</p>
{% endblock %}
about.html
模板文件继承自base.html
。 它添加了特定于此页面的数据。 我们避免代码重复; 我们不会在两个页面上重复相同的标签,例如body
和html
和meta
标签。
{% extends 'base.html' %}
继承是通过extends
指令完成的。
{% block title%}About page{% endblock %}
我们定义一个标题。
{% block content %}
<h1>About page</h1>
<p>
This is about page
</p>
{% endblock %}
并且我们定义内容。
Jinja Flask 示例
在下一个示例中,我们创建一个使用 Jinja 的简单 Flask 应用。
app.py
#!/usr/bin/env python3
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route("/greet")
def greet():
username = request.args.get('name')
return render_template('index.html', name=username)
if __name__ == "__main__":
app.run()
在此 Flask 应用中,我们获取用户名,并将其作为参数传递给render_template()
方法。 greet()
函数对/greet
路径做出反应。
templates/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Greeting</title>
</head>
<body>
<p>
Hello {{ name }}
</p>
</body>
</html>
这是模板文件,位于templates
目录中。 我们使用{{ name }}
语法将用户名添加到模板文件中。
$ python3 app.py
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
我们启动服务器。
$ curl http://127.0.0.1:5000/greet?name=Peter
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Greeting</title>
</head>
<body>
<p>
Hello Peter
</p>
</body>
</html>
我们使用curl
工具连接到应用。 我们添加一个名称参数。
在本教程中,我们介绍了 Python Jinja 模块。
您可能也对以下相关教程感兴趣: PyMongo 教程, Python 日志记录教程, pyDAL 教程和 Python 教程。
{% endraw %}