开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

Python 使用 Jinja

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教程。

未经允许不得转载:我爱分享网 » Python 使用 Jinja

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏