Jinja教程展示了如何使用Jinja模块在Python中创建模板。
PythonJinja模块
Jinja是Python的模板引擎。它类似于Django模板引擎。
模板引擎或模板处理器是一个库,旨在将模板与数据模型结合起来以生成文档。模板引擎通常用于生成大量电子邮件、源代码预处理或生成动态HTML页面。
我们创建了一个模板引擎,我们在其中定义了静态部分和动态部分。动态部分稍后被数据替换。渲染函数稍后将模板与数据结合起来。
Jinja安装
$ sudo pip3 install jinja2
我们使用pip3
工具来安装Jinja。
Jinja分隔符
Jinja在模板字符串中使用各种分隔符。
{%%}
-语句{{}}
-打印到模板输出的表达式{##}
-不包含在模板输出中的注释###
-行语句
Jinja简单示例
在第一个示例中,我们创建了一个非常简单的模板。
#!/usr/bin/python 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
这是一个示例输出。
在下一个示例中,我们使用两个变量。
#!/usr/bin/python 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
神社对象
我们可以在模板字符串中使用对象。
#!/usr/bin/python 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
对象。我们通过两个getter获得了name和age。
字典
Jinja允许使用方便的点符号来访问Python字典中的数据。
#!/usr/bin/python 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'] }}")
active和commented方式都有效。点符号更方便。
Jinja原始数据
我们可以使用raw
,endraw
标记来转义Jinja定界符。
#!/usr/bin/python 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
函数。
#!/usr/bin/python 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))
escape函数做同样的事情。
表达式的Jinja
for表达式用于迭代模板中的数据集合。
现在我们不再使用简单的字符串模板了。我们使用一个用FileSystemLoader
加载的文本文件。
#!/usr/bin/python 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
方法获取模板。
{% for person in persons -%} {{ person.name }} {{ person.age }} {% endfor %}
在模板文件中,我们使用for表达式迭代集合。我们显示此人的姓名和年龄。%字符旁边的破折号字符用于控制空格。
Jinja条件句
条件是满足特定条件时计算的表达式。
#!/usr/bin/python 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
输出中的空白可以通过环境属性来控制。
{% for person in persons %} {% if person.age < 18 %} {{- person.name }} {% endif %} {%- endfor %}
在模板中,我们使用if表达式只输出18岁以下的人。
$ ./conditionals.py Mark Lucy
Jinja求和过滤器
过滤器可以应用于数据以修改它们。例如,sumfilter可以对数据求和,escapefilter对数据进行转义,sortfilter对数据进行排序。
#!/usr/bin/python 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} ]
我们有一份汽车词典列表。每个字典都有一个价格键。它将用于计算总和。
The sum of car prices is {{ cars | sum(attribute='price') }}
在模板文件中,我们将过滤器应用于汽车集合对象。总和是根据price
属性计算的。
$ ./sum_filter.py The sum of car prices is 105900
Jinja模板继承
模板继承是一种强大的功能,可以减少代码重复并改进代码组织。我们定义了一个基本模板,我们从中继承其他模板文件。这些模板文件覆盖基本模板文件的特定块。
#!/usr/bin/python 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
文件。
<!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
文件中,我们声明了两个块:标题和内容。这些块将在子模板中填充特定的标签和文本。
{% 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 %}
我们定义内容。
JinjaFlask示例
在下一个示例中,我们将创建一个使用Jinja的简单Flask应用程序。
#!/usr/bin/python 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
路径作出反应。
<!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
工具连接到应用程序。我们添加一个名称参数。
在本教程中,我们介绍了PythonJinja模块。
列出所有Python教程。