Homepage, Documentation, 文档Python2, github
Jinja 是一个快速、富有表现力、可扩展的模板引擎。模板中的特殊占位符允许编写类似于 Python 语法的代码。然后向模板传递数据以呈现最终文档。
它包括:
Jinja 的理念是,虽然应用程序逻辑尽可能属于 Python,但它不应该通过过多地限制功能来使模板设计者的工作变得困难。
xxxxxxxxxx{% extends "base.html" %}{% block title %}Members{% endblock %}{% block content %} <ul> {% for user in users %} <li><a href="{{ user.url }}">{{ user.username }}</a></li> {% endfor %} </ul>{% endblock %}T0uken于 2024-08-24 02:34:37 发布
Jinja2 是一个广泛使用的 Python 模板引擎,它允许你使用模板语法生成动态的 HTML、XML、或者其他文本文件。Jinja2 是 Flask 和 FastAPI 等 Web 框架中默认的模板引擎,但它也可以在任何 Python 项目中独立使用。
xxxxxxxxxxpip install jinja2xxxxxxxxxxfrom jinja2 import Environment, FileSystemLoaderjinja2 是 Jinja2 模板引擎的 Python 模块。
Environment是 Jinja2 的核心类之一,负责管理模板的全局配置、变量的全局设置,以及模板文件的加载方式。
Environment 的作用:这个类用于创建模板环境,管理模板的全局配置,如自动转义、缓存设置、扩展的使用等。在 Environment 对象中,可以定义如何加载模板、模板的编码格式、全局变量和过滤器等。FileSystemLoader是 Jinja2 中的一种加载器,用于从文件系统中的指定目录加载模板文件。
FileSystemLoader 是其中最常用的一种,适用于从文件系统加载模板。加载器的作用是告诉 Jinja2 如何找到和读取模板文件。xxxxxxxxxxenv = Environment(loader=FileSystemLoader('templates'))env:这是一个Environment类的实例,代表 Jinja2 模板的全局环境。
Environment 的实例化:通过 Environment() 创建的 env 对象,负责管理和存储所有模板相关的配置和信息。loader=FileSystemLoader('templates'):
loader 参数:Environment 类的一个关键参数,用于指定模板文件的加载器。在这里,我们使用 FileSystemLoader 加载器。FileSystemLoader('templates'):指定了模板文件所在的目录'templates',表示所有的模板文件都存放在这个文件夹中。作用:当你在后续代码中请求模板时,Jinja2 会在 templates 目录中查找相应的模板文件。
代码扩展:
可以在 Environment 中传递更多的配置参数,例如:
xxxxxxxxxxenv = Environment( loader=FileSystemLoader('templates'), autoescape=True, # 自动转义 HTML 特殊字符,防止 XSS 攻击 cache_size=50, # 设置缓存大小,提高模板加载的效率 trim_blocks=True, # 去除块级标签中的空白行 lstrip_blocks=True # 去除块级标签前的空白字符)
xxxxxxxxxxtemplate = env.get_template('my_template.html')
template:这是一个 Template 对象,表示加载的模板文件。
template 对象持有了 my_template.html 模板的内容,可以使用这个对象进行渲染操作。env.get_template('my_template.html'):
get_template 方法:这是 Environment 类的一个方法,用于加载指定的模板文件。
参数 'my_template.html':指定了要加载的模板文件的名称。
FileSystemLoader 指定的目录(即 'templates' 文件夹)中查找名为 my_template.html 的文件,并将其作为模板进行加载。返回值:get_template() 方法返回一个 Template 对象,代表该模板文件,可以使用它进行渲染。
代码扩展:
处理不存在的模板文件:
如果模板文件不存在,get_template 会抛出 TemplateNotFound 异常。你可以通过 try...except 结构来处理这个错误。
xxxxxxxxxxtry: template = env.get_template('non_existent_template.html')except TemplateNotFound: print("Template file not found!")
xxxxxxxxxxrendered_html = template.render(user_name="Alice", user_is_admin=True)
rendered_html:这是一个字符串变量,存储了渲染后的 HTML 或其他格式的内容。
rendered_html 是模板渲染的最终结果,即在模板中填充变量后的完整内容,通常是 HTML 代码,但也可以是任何字符串形式的内容(例如纯文本、JSON 等)。template.render():
render 方法:这是 Template 类的一个方法,用于将模板中的占位符替换为实际的值,从而生成最终的输出。render 方法会解析模板中的变量和控制结构,将传递的实际值插入到模板中,生成渲染后的内容。参数传递:
user_name="Alice":向模板传递一个名为 user_name 的变量,值为 "Alice" 。
user_name 变量的地方都会被替换为 "Alice"。user_is_admin=True:向模板传递一个名为 user_is_admin 的布尔变量,值为 True 。
user_is_admin 变量的地方都会被替换为 True,并且可以用于控制结构(如条件语句)来决定是否显示特定内容。代码扩展:
假设我们有以下模板 my_template.html:
xxxxxxxxxx<html><head> <title>User Info</title></head><body> <h1>Welcome, {{ user_name }}!</h1> {% if user_is_admin %} <p>You have admin privileges.</p> {% else %} <p>You are a regular user.</p> {% endif %}</body></html>
当我们使用 template.render(user_name="Alice", user_is_admin=True) 渲染这个模板时,最终生成的 rendered_html 将是:
xxxxxxxxxx<html><head> <title>User Info</title></head><body> <h1>Welcome, Alice!</h1> <p>You have admin privileges.</p></body></html>
除了单一变量传递外,render 方法可以接受任意数量的键值对参数:
xxxxxxxxxxrendered_html = template.render( user_name="Bob", user_is_admin=False, greeting="Hello", notifications=5)
对应的模板可能会这样写:
xxxxxxxxxx<h1>{{ greeting }}, {{ user_name }}!</h1>{% if notifications > 0 %}<p>You have {{ notifications }} new notifications.</p>{% else %}<p>No new notifications.</p>{% endif %}
渲染结果会是:
xxxxxxxxxx<h1>Hello, Bob!</h1><p>You have 5 new notifications.</p>
Jinja2 允许在模板中使用双花括号 {{ }} 语法插入变量。变量插值是 Jinja2 最基本的功能之一,通常用于动态生成内容。
xxxxxxxxxx<html lang="en"><head> <meta charset="UTF-8"> <title>Welcome Page</title></head><body> <h1>Hello, {{ user_name }}!</h1> <p>Welcome to our website. Your email is: {{ user_email }}</p></body></html>
xxxxxxxxxxfrom jinja2 import Environment, FileSystemLoader
# 创建 Jinja2 环境,指定模板文件的路径env = Environment(loader=FileSystemLoader('templates'))
# 加载模板文件template = env.get_template('welcome.html')
# 定义模板中需要插入的变量context = { 'user_name': 'Alice', 'user_email': 'alice@example.com'}
# 渲染模板并生成最终的 HTMLrendered_html = template.render(context)print(rendered_html)
变量插值:{{ user_name }} 会在最终的 HTML 中被替换为 Alice,{{ user_email }} 会被替换为 alice@example.com。
输出:最终生成的 HTML 将是:
xxxxxxxxxx<h1>Hello, Alice!</h1><p>Welcome to our website. Your email is: alice@example.com</p>12Jinja2 支持常见的控制结构,如条件语句 (if)、循环 (for),这使得模板能够根据条件或数据动态生成不同的内容。
xxxxxxxxxx<html lang="en"><head> <meta charset="UTF-8"> <title>User Dashboard</title></head><body> <h1>Dashboard</h1> {% if user_is_admin %} <p>Welcome, admin! You have full access to the system.</p> {% else %} <p>Welcome, user! Your access is limited.</p> {% endif %}</body></html>
context = { 'user_is_admin': True}
rendered_html = template.render(context)print(rendered_html)
xxxxxxxxxx<html lang="en"><head> <meta charset="UTF-8"> <title>Product List</title></head><body> <h1>Available Products</h1> <ul> {% for product in products %} <li>{{ product.name }} - ${{ product.price }}</li> {% else %} <li>No products available</li> {% endfor %} </ul></body></html>
xxxxxxxxxxcontext = { 'products': [ {'name': 'Laptop', 'price': 1200}, {'name': 'Smartphone', 'price': 800}, {'name': 'Tablet', 'price': 450} ]}
rendered_html = template.render(context)print(rendered_html)
条件语句:{% if user_is_admin %} 判断用户是否为管理员,输出相应的欢迎信息。
循环:{% for product in products %} 遍历 products 列表,生成每个产品的列表项。如果 products 列表为空,{% else %} 分支会显示 “No products available”。
输出
:
xxxxxxxxxx<ul> <li>Laptop - $1200</li> <li>Smartphone - $800</li> <li>Tablet - $450</li></ul>12345Jinja2 提供了一系列内置过滤器,用于在模板中对变量进行格式化和处理。过滤器使用管道符号 | 进行应用,类似于 Unix 的管道操作。
upper:将字符串转换为大写。lower:将字符串转换为小写。date:格式化日期。length:获取列表或字符串的长度。xxxxxxxxxx<html lang="en"><head> <meta charset="UTF-8"> <title>User Profile</title></head><body> <h1>User Profile</h1> <p>Name: {{ user_name | upper }}</p> <p>Member since: {{ join_date | date("Y-m-d") }}</p> <p>You have {{ notifications | length }} new notifications.</p></body></html>
xxxxxxxxxxfrom datetime import datetime
context = { 'user_name': 'Alice', 'join_date': datetime(2021, 3, 15), 'notifications': ['Message 1', 'Message 2', 'Message 3']}
rendered_html = template.render(context)print(rendered_html)
upper 过滤器:将 user_name 转换为大写,即 Alice 变为 ALICE。date 过滤器:将 join_date 格式化为 YYYY-MM-DD 格式,如 2021-03-15。length 过滤器:计算 notifications 列表的长度,即显示 “You have 3 new notifications”。模板继承是 Jinja2 的一大特色,它允许你定义一个基础模板,并在其他模板中继承和扩展该基础模板。这有助于保持代码的可维护性和一致性,尤其是在处理大型项目时。
base.html):xxxxxxxxxx<html lang="en"><head> <meta charset="UTF-8"> <title>{% block title %}My Website{% endblock %}</title></head><body> <header> <h1>My Website</h1> <nav> <a href="/">Home</a> <a href="/about">About</a> <a href="/contact">Contact</a> </nav> </header> <main> {% block content %}{% endblock %} </main> <footer> <p>© 2024 My Website</p> </footer></body></html>
home.html):xxxxxxxxxx{% extends "base.html" %}
{% block title %}Home - My Website{% endblock %}
{% block content %} <h2>Welcome to the Home Page</h2> <p>This is the main content of the home page.</p>{% endblock %}
xxxxxxxxxxtemplate = env.get_template('home.html')rendered_html = template.render()print(rendered_html)
{% extends "base.html" %}:home.html 继承了 base.html 中定义的结构和样式。
{% block title %} 和 {% block content %}:子模板通过 block 标签重写了 base.html 中的特定部分,如标题和主要内容。
输出:
xxxxxxxxxx<title>Home - My Website</title><h2>Welcome to the Home Page</h2><p>This is the main content of the home page.</p>123宏类似于 Python 中的函数,用于封装可重用的模板代码。使用宏可以避免重复代码,并简化复杂的模板逻辑。
xxxxxxxxxx{% macro render_input(name, value='', type='text', placeholder='') %} <input type="{{ type }}" name="{{ name }}" value="{{ value }}" placeholder="{{ placeholder }}">{% endmacro %}
<form> {{ render_input('username', type='text', placeholder='Enter your username') }} {{ render_input('password', type='password', placeholder='Enter your password') }} <button type="submit">Login</button></form>
xxxxxxxxxxtemplate = env.get_template('form.html')rendered_html = template.render()print(rendered_html)
{% macro render_input %}:定义了一个名为 render_input 的宏,用于生成 <input> 表单元素。这个宏接收多个参数,如 name、value、type 和 placeholder。
宏的使用:通过调用 {{ render_input(...) }},可以生成自定义的输入框,而不需要重复编写 HTML 代码。
输出:
xxxxxxxxxx <input type="text" name="username" value="" placeholder="Enter your username"> <input type="password" name="password" value="" placeholder="Enter your password"> <button type="submit">Login</button>
在 FastAPI 中使用 Jinja2 渲染和返回动态页面是一种常见的做法,尤其是在需要生成动态 HTML 内容时。以下是详细步骤和代码示例,展示如何在 FastAPI 中集成 Jinja2 并返回动态页面。
首先,确保安装了 FastAPI 和 Jinja2 相关的依赖包:
xxxxxxxxxxpip install fastapi jinja2 uvicorn
假设你的项目结构如下:
xxxxxxxxxx.├── app.py├── templates│ └── index.html
app.py: 主应用程序文件。templates: 存放 Jinja2 模板文件的目录。index.html: 一个示例模板文件。在 app.py 中设置 FastAPI 应用程序并配置 Jinja2 进行模板渲染:
xxxxxxxxxxfrom fastapi import FastAPI, Requestfrom fastapi.templating import Jinja2Templatesfrom fastapi.responses import HTMLResponse
app = FastAPI()
# 配置 Jinja2 模板引擎templates = Jinja2Templates(directory="templates")
.get("/", response_class=HTMLResponse)async def read_root(request: Request): # 渲染 index.html 模板,并传递上下文变量 return templates.TemplateResponse("index.html", {"request": request, "user_name": "Alice", "user_is_admin": True})
Jinja2Templates(directory="templates"): 这行代码配置了 Jinja2 模板引擎,指定模板文件存放在 templates 目录下。
@app.get("/", response_class=HTMLResponse): 这个装饰器用于定义一个 GET 路由,当用户访问 / 时,这个函数会被调用。
TemplateResponse("index.html", {"request": request, "user_name": "Alice", "user_is_admin": True}) :
TemplateResponse: 渲染 Jinja2 模板并返回一个 HTML 响应。"index.html": 指定要渲染的模板文件。{"request": request, "user_name": "Alice", "user_is_admin": True}: 传递给模板的上下文数据,request 对象是必须的,它用于模板内部访问 URL 路径等信息,其他变量如 user_name 和 user_is_admin 可以在模板中使用。在 templates 目录下创建 index.html 文件:
xxxxxxxxxx<html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Welcome</title></head><body> <h1>Welcome, {{ user_name }}!</h1> {% if user_is_admin %} <p>You have admin privileges.</p> {% else %} <p>You are a regular user.</p> {% endif %}</body></html>
{{ user_name }}: 用于插入 user_name 变量的值。{% if user_is_admin %}: 控制结构,用于根据 user_is_admin 的值显示不同的内容。在终端中启动 Uvicorn 服务器以运行 FastAPI 应用:
xxxxxxxxxxuvicorn app:app --reload
然后访问 http://127.0.0.1:8000/,你将看到渲染后的 HTML 页面。
Google Translate from: https://jinja.palletsprojects.com/en/stable/templates/
本文档描述了模板引擎的语法和语义,对于创建 Jinja 模板的人来说非常有用。由于模板引擎非常灵活,因此应用程序中的配置在分隔符和未定义值的行为方面可能与此处提供的代码略有不同。
Jinja 模板只是一个文本文件。Jinja 可以生成任何基于文本的格式(HTML、XML、CSV、LaTeX 等)。Jinja 模板不需要有特定的扩展名:.html、.xml或任何其他扩展名都可以。
模板包含变量和/或表达式,在模板呈现时它们会被替换为值;以及标签,用于控制模板的逻辑。模板语法深受 Django 和 Python 的启发。
下面是一个最小模板,它说明了使用默认 Jinja 配置的一些基本知识。我们将在本文档的后面部分介绍详细信息:
xxxxxxxxxx<!DOCTYPE html><html lang="en"><head><title>My Webpage</title></head><body><ul id="navigation">{% for item in navigation %}<li><a href="{{ item.href }}">{{ item.caption }}</a></li>{% endfor %}</ul><h1>My Webpage</h1>{{ a_variable }}{# a comment #}</body></html>
以下示例显示了默认配置设置。应用程序开发人员可以将语法配置从更改为或类似内容。{% foo %}``<% foo %>
分隔符有几种。默认的 Jinja 分隔符配置如下:
行语句和注释也是可能的,但它们没有默认前缀字符。要使用它们,请 在创建时 line_statement_prefix和。line_comment_prefixEnvironment
如上所述,任何文件都可以作为模板加载,无论文件扩展名是什么。添加.jinja扩展名(例如)user.html.jinja 可能会使某些 IDE 或编辑器插件更容易使用,但这不是必需的。稍后介绍的自动转义可以根据文件扩展名应用,因此在这种情况下您需要考虑额外的后缀。
识别模板的另一个好方法是,它们位于 templates文件夹中,无论扩展名是什么。这是项目的常见布局。
模板变量由传递给模板的上下文字典定义。
只要模板中的变量是由应用程序传入的,您就可以随意使用它们。变量可能具有您也可以访问的属性或元素。变量具有哪些属性在很大程度上取决于提供该变量的应用程序。
除了标准 Python “下标”语法( )之外,还可以使用点(.)来访问变量的属性。__getitem__``[]
以下几行做同样的事情:
xxxxxxxxxx{{ foo.bar }}{{ foo['bar'] }}
重要的是要知道,外部双花括号不是变量的一部分,而是打印语句的一部分。如果您访问标签内的变量,请不要将括号括起来。
如果变量或属性不存在,您将返回未定义的值。您可以对这种值执行的操作取决于应用程序配置:默认行为是,如果打印或迭代,则计算结果为空字符串,而对于其他所有操作,则计算结果为失败。
执行
为了方便起见,foo.barJinja 在 Python 层做了以下事情:
bar上调用的属性foo``getattr(foo, 'bar')'bar'中的项目foo``foo.__getitem__('bar')foo['bar']工作原理基本相同,只是顺序略有不同:
'bar'检查中的项目foo。(foo.__getitem__('bar'))bar。foo()getattr(foo, 'bar')如果对象有同名的项目和属性,这一点很重要。此外,attr()过滤器仅查找属性。
变量可以通过过滤器进行修改。过滤器与变量之间用竖线符号 ( ) 分隔|,并且可以在括号中带有可选参数。可以串联多个过滤器。一个过滤器的输出将应用于下一个过滤器。
例如,将从变量中删除所有 HTML 标签并将输出改为标题大小写()。{{ name|striptags|title }}``name``title(striptags(name))
接受参数的过滤器在参数周围有括号,就像函数调用一样。例如:将使用逗号 ( ) 连接列表。{{ listx|join(', ') }}``str.join(', ', listx)
下面的内置过滤器列表描述了所有内置过滤器。
除了过滤器之外,还有所谓的“测试”可用。测试可用于根据常见表达式测试变量。要测试变量或表达式,请is在变量后添加测试名称。例如,要确定变量是否已定义,您可以执行,然后它将根据当前模板上下文中是否已定义返回 true 或 false。name is defined``name
测试也可以接受参数。如果测试只接受一个参数,则可以省略括号。例如,以下两个表达式执行相同的操作:
xxxxxxxxxx{% if loop.index is divisibleby 3 %}{% if loop.index is divisibleby(3) %}
下面的内置测试列表描述了所有内置测试。
要注释掉模板中某一行的某部分,请使用注释语法,该语法默认设置为。这对于注释掉模板的某些部分以进行调试或为其他模板设计者或您自己添加信息非常有用:{# ... #}
xxxxxxxxxx{# note: commented-out template because we no longer use this{% for user in users %}...{% endfor %}#}
在默认配置中:
如果应用程序将 Jinja 配置为trim_blocks,则会自动删除模板标记后的第一个换行符(就像在 PHP 中一样)。lstrip_blocks 还可以将选项设置为从行首到块开头删除制表符和空格。 (如果块开头之前有其他字符,则不会删除任何内容。)
当同时禁用trim_blocks和lstrip_blocks时(默认),块标签所在的行将被删除,但会保留一个空白行,并且内容中的空格将被保留。例如,此模板:
xxxxxxxxxx<div>{% if True %}yay{% endif %}</div>
当和都trim_blocks禁用时lstrip_blocks,模板将在 div 内呈现空行:
xxxxxxxxxx<div>yay</div>
当trim_blocks和都lstrip_blocks启用时,模板块行将被完全删除:
xxxxxxxxxx<div>yay</div>
您可以通过在块开头lstrip_blocks放置加号 ( ) 来手动禁用该行为:+
xxxxxxxxxx<div>{%+ if something %}yay{% endif %}</div>
类似地,您可以通过在块末尾trim_blocks放置加号()来手动禁用该行为:+
xxxxxxxxxx<div>{% if something +%}yay{% endif %}</div>
您还可以手动去除模板中的空格。如果您-在块(例如For标签)、注释或变量表达式的开头或结尾添加减号 ( ),则该块之前或之后的空格将被删除:
xxxxxxxxxx{% for item in seq -%}{{ item }}{%- endfor %}
这将输出所有元素之间没有空格。如果是从到的seq数字列表,则输出为。1``9``123456789
如果启用了行语句,它们会自动删除行首之前的空格。
默认情况下,Jinja 还会删除尾随换行符。要保留单个尾随换行符,请将 Jinja 配置为keep_trailing_newline。
笔记
标签和减号之间不能添加空格。
有效的:
xxxxxxxxxx{%- if foo -%}...{% endif %}
无效的:
xxxxxxxxxx{% - if foo - %}...{% endif %}
有时,让 Jinja 忽略它本来会作为变量或块处理的部分是可取的(甚至是必要的)。例如,如果使用默认语法,您想{{在模板中将其用作原始字符串而不是启动变量,则必须使用技巧。
输出文字变量分隔符({{)的最简单方法是使用变量表达式:
xxxxxxxxxx{{ '{{' }}
对于较大的部分,标记一个块是有意义的raw。例如,要在模板中包含示例 Jinja 语法,您可以使用此代码片段:
xxxxxxxxxx{% raw %}<ul>{% for item in seq %}<li>{{ item }}</li>{% endfor %}</ul>{% endraw %}
笔记
标签末尾的减号会清除原始数据第一个字符之前的所有空格和换行符。{% raw -%}
如果应用程序启用了行语句,则可以将行标记为语句。例如,如果将行语句前缀配置为#,则以下两个示例是等效的:
xxxxxxxxxx<ul># for item in seq<li>{{ item }}</li># endfor</ul><ul>{% for item in seq %}<li>{{ item }}</li>{% endfor %}</ul>
行语句前缀可以出现在行中的任何位置,只要它前面没有文本即可。为了提高可读性,以块开头的语句(例如 for、等)可以以冒号结尾:if``elif
xxxxxxxxxx# for item in seq:...# endfor
笔记
如果有左括号、大括号或方括号,行语句可以跨越多行:
xxxxxxxxxx<ul># for href, caption in [('index.html', 'Index'),('about.html', 'About')]:<li><a href="{{ href }}">{{ caption }}</a></li># endfor</ul>
从 Jinja 2.2 开始,基于行的注释也可用。例如,如果将行注释前缀配置为##,则从##行到行尾的所有内容都将被忽略(换行符除外):
xxxxxxxxxx# for item in seq:<li>{{ item }}</li> ## this comment is ignored# endfor
Jinja 最强大的部分是模板继承。模板继承允许您构建一个基本“骨架”模板,其中包含站点的所有常见元素,并定义子模板可以覆盖的块。
听起来很复杂,但其实很简单。从一个例子开始最容易理解。
这个模板,我们称之为base.html,定义了一个简单的 HTML 骨架文档,您可以将其用于简单的两列页面。“子”模板的工作是用内容填充空白块:
xxxxxxxxxx<!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 %}© Copyright 2008 by <a href="http://domain.invalid/">you</a>.{% endblock %}</div></body></html>
在这个例子中,标签定义了子模板可以填充的四个块。标签所做的就是告诉模板引擎子模板可能会覆盖模板中的那些占位符。{% block %}``block
block标签可以位于其他块内,例如if,但无论if块是否实际呈现,它们都会始终被执行。
子模板可能如下所示:
xxxxxxxxxx{% extends "base.html" %}{% block title %}Index{% endblock %}{% block head %}{{ super() }}<style type="text/css">.important { color: #336699; }</style>{% endblock %}{% block content %}<h1>Index</h1><p class="important">Welcome to my awesome homepage.</p>{% endblock %}
标签是这里的关键。它告诉模板引擎此模板“扩展”了另一个模板。当模板系统评估此模板时,它首先定位父级。extends 标签应该是模板中的第一个标签。它之前的所有内容都会正常打印出来,可能会引起混淆。有关此行为以及如何利用它的详细信息,请参阅Null-Default Fallback。此外,无论周围条件的评估结果为真还是假,块都会始终被填充。{% extends %}
模板的文件名取决于模板加载器。例如, FileSystemLoader允许您通过提供文件名来访问其他模板。您可以使用斜杠访问子目录中的模板:
xxxxxxxxxx{% extends "layout/default.html" %}
但此行为可能取决于嵌入 Jinja 的应用程序。请注意,由于子模板未定义footer块,因此将使用父模板中的值。
您不能在同一个模板中定义多个同名的标签。存在此限制是因为块标签在“两个”方向上都起作用。也就是说,块标签不仅提供要填充的占位符 - 它还定义填充父级中占位符的内容。如果模板中有两个名称相似的标签,则该模板的父级将不知道要使用哪个块的内容。{% block %}``{% block %}
但是,如果您想多次打印一个块,则可以使用特殊 self变量并调用具有该名称的块:
xxxxxxxxxx<title>{% block title %}{% endblock %}</title><h1>{{ self.title() }}</h1>{% block body %}{% endblock %}
可以通过调用 来渲染父块的内容super()。这将返回父块的结果:
xxxxxxxxxx{% block sidebar %}<h3>Table Of Contents</h3>...{{ super() }}{% endblock %}
在有多个级别的情况下, 可以通过链接引用(如)来跳过继承树中的级别。{% extends %}``super``super.super()
例如:
xxxxxxxxxx# parent.tmplbody: {% block body %}Hi from parent.{% endblock %}# child.tmpl{% extends "parent.tmpl" %}{% block body %}Hi from child. {{ super() }}{% endblock %}# grandchild1.tmpl{% extends "child.tmpl" %}{% block body %}Hi from grandchild1.{% endblock %}# grandchild2.tmpl{% extends "child.tmpl" %}{% block body %}Hi from grandchild2. {{ super.super() }} {% endblock %}
渲染child.tmpl将给出 body: Hi from child. Hi from parent.
渲染grandchild1.tmpl将给出 body: Hi from grandchild1.
渲染grandchild2.tmpl将给出 body: Hi from grandchild2. Hi from parent.
Jinja 允许您将块的名称放在结束标记之后,以提高可读性:
xxxxxxxxxx{% block sidebar %}{% block inner_sidebar %}...{% endblock inner_sidebar %}{% endblock sidebar %}
但是单词后面的名称endblock必须与块名称相匹配。
块可以嵌套以实现更复杂的布局。默认情况下,块不能访问块外部的变量(外部作用域):
xxxxxxxxxx{% for item in seq %}<li>{% block loop_item %}{{ item }}{% endblock %}</li>{% endfor %}
此示例将输出空<li>项,因为item块内不可用。原因是如果块被子模板替换,则会出现一个未在块中定义或未传递给上下文的变量。
scoped 从 Jinja 2.2 开始,您可以通过在块声明中添加修饰符将块设置为“作用域”,从而明确指定块中的变量可用:
xxxxxxxxxx{% for item in seq %}<li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>{% endfor %}
覆盖块时,scoped不必提供修饰符。
块可以标记为required。它们必须在某个时候被覆盖,但不一定由直接子模板覆盖。必需的块可能只包含空格和注释,并且不能直接呈现。
xxxxxxxxxxpage.txt{% block body required %}{% endblock %}issue.txt{% extends "page.txt" %}bug_report.txt{% extends "issue.txt" %}{% block body %}Provide steps to demonstrate the bug.{% endblock %}
渲染page.txt或issue.txt将引发 TemplateRuntimeError,因为它们不会覆盖body块。渲染bug_report.txt将成功,因为它会覆盖块。
与 结合使用时scoped,required修饰符必须放在 作用域修饰符之后。以下是一些有效示例:
xxxxxxxxxx{% block body scoped %}{% endblock %}{% block body required %}{% endblock %}{% block body scoped required %}{% endblock %}
extends、include和import可以采用模板对象而不是要加载的模板名称。这在某些高级情况下可能很有用,因为您可以使用 Python 代码先加载模板并将其传递给render。
xxxxxxxxxxif debug_mode:layout = env.get_template("debug_layout.html")else:layout = env.get_template("layout.html")user_detail = env.get_template("user/detail.html")return user_detail.render(layout=layout){% extends layout %}
注意如何extends将变量与传递给的模板对象一起传递render,而不是字符串。
从模板生成 HTML 时,变量中包含的字符可能会影响生成的 HTML,这种风险始终存在。有两种方法:
Jinja 支持这两种方式。具体使用哪种方式取决于应用程序配置。默认配置是没有自动转义的;原因如下:
如果启用了手动转义,则您有责任在需要时转义变量。要转义什么?如果您的变量可能 包含以下任何字符(>、<、&或"),则除非变量包含格式正确且受信任的 HTML,否则您 应该对其进行转义。转义通过将变量通过|e过滤器进行管道传输来实现:
xxxxxxxxxx{{ user.username|e }}
启用自动转义后,除了明确标记为安全的值之外,所有内容都会默认转义。变量和表达式可以在以下任一情况下标记为安全:
markupsafe.Markup|safe过滤器。如果您标记为安全的字符串通过无法理解该标记的其他 Python 代码传递,则可能会丢失。请注意您的数据何时被标记为安全以及在到达模板之前如何处理它。
如果某个值已转义但未标记为安全,则仍将进行自动转义并导致出现双转义字符。如果您知道您有已经安全但未标记的数据,请务必将其包装起来 Markup或使用|safe过滤器。
Jinja 函数(宏super、、self.BLOCKNAME)始终返回标记为安全的模板数据。
具有自动转义的模板中的字符串文字被认为是不安全的,因为原生 Python 字符串并不安全。
控制结构是指控制程序流程的所有内容 - 条件(即 if/elif/else)、for 循环以及宏和块之类的内容。使用默认语法,控制结构出现在 块内。{% ... %}
循环遍历序列中的每个项目。例如,要显示名为的变量中提供的用户列表users:
xxxxxxxxxx<h1>Members</h1><ul>{% for user in users %}<li>{{ user.username|e }}</li>{% endfor %}</ul>
由于模板中的变量保留其对象属性,因此可以对容器进行迭代,例如dict:
xxxxxxxxxx<dl>{% for key, value in my_dict.items() %}<dt>{{ key|e }}</dt><dd>{{ value|e }}</dd>{% endfor %}</dl>
Python 字典的显示顺序可能不符合您的要求。如果顺序很重要,请使用|dictsort过滤器。
xxxxxxxxxx<dl>{% for key, value in my_dict | dictsort %}<dt>{{ key|e }}</dt><dd>{{ value|e }}</dd>{% endfor %}</dl>
在 for 循环块中,你可以访问一些特殊变量:
| 多变的 | 描述 |
|---|---|
loop.index | 循环的当前迭代。(1 个索引) |
loop.index0 | 循环的当前迭代。(0 索引) |
loop.revindex | 从循环末尾开始的迭代次数(1 索引) |
loop.revindex0 | 从循环末尾开始的迭代次数(0 索引) |
loop.first | 如果是第一次迭代则为真。 |
loop.last | 如果是最后一次迭代则为真。 |
loop.length | 序列中的项目数。 |
loop.cycle | 用于在序列列表之间循环的辅助函数。请参阅下面的说明。 |
loop.depth | 指示渲染当前处于递归循环的深度。从第 1 级开始 |
loop.depth0 | 指示渲染当前处于递归循环的深度。从 0 级开始 |
loop.previtem | 循环中上一次迭代的项目。第一次迭代期间未定义。 |
loop.nextitem | 循环中下一次迭代的项目。上次迭代期间未定义。 |
loop.changed(*val) | 如果之前使用不同的值调用(或根本没有调用),则为 True。 |
在 for 循环中,可以使用特殊loop.cycle帮助器在每次循环中循环字符串/变量列表:
xxxxxxxxxx{% for row in rows %}<li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>{% endfor %}
从 Jinja 2.1 开始,cycle有一个额外的辅助函数允许进行不受循环约束的循环。有关更多信息,请查看全局函数列表。
与 Python 不同,无法在循环中使用break或continue。但是,您可以在迭代过程中过滤序列,这样您就可以跳过项目。以下示例跳过所有隐藏的用户:
xxxxxxxxxx{% for user in users if not user.hidden %}<li>{{ user.username|e }}</li>{% endfor %}
优点是特殊loop变量将正确计数;因此不计算未迭代的用户。
如果由于序列为空或过滤从序列中删除了所有项目而没有进行迭代,则可以使用以下命令呈现默认块else:
xxxxxxxxxx<ul>{% for user in users %}<li>{{ user.username|e }}</li>{% else %}<li><em>no users found</em></li>{% endfor %}</ul>
请注意,在 Python 中,else只要相应的循环未执行, break就会执行块。由于 Jinja 循环无论如何都无法执行,因此选择了break略有不同的关键字行为。else
也可以使用递归循环。如果您要处理站点地图或 RDFa 等递归数据,这很有用。要使用递归循环,您基本上必须recursive在循环定义中添加修饰符,并loop在要递归的位置使用新的可迭代对象调用变量。
以下示例实现了具有递归循环的站点地图:
xxxxxxxxxx<ul class="sitemap">{%- for item in sitemap recursive %}<li><a href="{{ item.href|e }}">{{ item.title }}</a>{%- if item.children -%}<ul class="submenu">{{ loop(item.children) }}</ul>{%- endif %}</li>{%- endfor %}</ul>
该loop变量始终引用最近(最内层)的循环。如果我们有多个循环级别,我们可以loop通过在要递归使用的循环后写入来重新绑定变量。然后,我们可以使用{% set outer_loop = loop %}``{{ outer_loop(...) }}
请注意,循环中的赋值将在迭代结束时被清除,并且不能超过循环范围。旧版本的 Jinja 有一个错误,在某些情况下,赋值似乎可以工作。这不受支持。有关如何处理此问题的更多信息,请参阅赋值。
如果您想要做的只是检查某个值自上次迭代以来是否发生了变化或者是否会在下一次迭代中发生变化,则可以使用previtem and nextitem:
xxxxxxxxxx{% for value in values %}{% if loop.previtem is defined and value > loop.previtem %}The value just increased!{% endif %}{{ value }}{% if loop.nextitem is defined and loop.nextitem > value %}The value will increase even more!{% endif %}{% endfor %}
如果你只关心值是否发生了变化,使用起来changed就更简单了:
xxxxxxxxxx{% for entry in entries %}{% if loop.changed(entry.category) %}<h2>{{ entry.category }}</h2>{% endif %}<p>{{ entry.message }}</p>{% endfor %}
Jinja 中的语句if与 Python 的 if 语句类似。在最简单的形式中,你可以使用它来测试变量是否已定义、不为空且不为 false:
xxxxxxxxxx{% if users %}<ul>{% for user in users %}<li>{{ user.username|e }}</li>{% endfor %}</ul>{% endif %}
对于多个分支,elif可以else像在 Python 中一样使用。您也可以在那里使用更复杂的表达式:
xxxxxxxxxx{% if kenny.sick %}Kenny is sick.{% elif kenny.dead %}You killed Kenny! You bastard!!!{% else %}Kenny looks okay --- so far{% endif %}
宏相当于常规编程语言中的函数。宏有助于将常用的习语放入可重用的函数中,从而避免重复(“DRY”)。
下面是一个呈现表单元素的宏的小示例:
xxxxxxxxxx{% macro input(name, value='', type='text', size=20) -%}<input type="{{ type }}" name="{{ name }}" value="{{value|e }}" size="{{ size }}">{%- endmacro %}
然后可以像命名空间中的函数一样调用该宏:
xxxxxxxxxx<p>{{ input('username') }}</p><p>{{ input('password', type='password') }}</p>
如果宏是在不同的模板中定义的,则必须 先导入它。
在宏内部,您可以访问三个特殊变量:
varargs
如果传递给宏的位置参数多于宏所接受的数量,它们最终会varargs作为值列表存入特殊变量中。
kwargs
类似varargs,但适用于关键字参数。所有未使用的关键字参数都存储在这个特殊变量中。
caller
如果从调用标签调用宏,则调用者将作为可调用宏存储在此变量中。
宏还会公开一些内部细节。宏对象具有以下属性:
name
宏的名称。 将打印。{{ input.name }}``input
arguments
宏接受的参数名称的元组。
catch_kwargs
true如果宏接受额外的关键字参数(即:访问特殊变量)就会出现这种情况kwargs。
catch_varargs
true如果宏接受额外的位置参数(即:访问特殊varargs变量)就会出现这种情况。
caller
true如果宏访问特殊变量并且可以从调用caller标签中调用,则会出现这种情况。
如果宏名以下划线开头,则不会导出也无法导入。
由于 Jinja 中作用域的工作方式,子模板中的宏不会覆盖父模板中的宏。下面将输出“LAYOUT”,而不是“CHILD”。
xxxxxxxxxxlayout.txt{% macro foo() %}LAYOUT{% endmacro %}{% block body %}{% endblock %}child.txt{% extends 'layout.txt' %}{% macro foo() %}CHILD{% endmacro %}{% block body %}{{ foo() }}{% endblock %}
在某些情况下,将一个宏传递给另一个宏会很有用。为此,您可以使用特殊call块。以下示例显示了一个利用调用功能的宏及其使用方法:
xxxxxxxxxx{% macro render_dialog(title, class='dialog') -%}<div class="{{ class }}"><h2>{{ title }}</h2><div class="contents">{{ caller() }}</div></div>{%- endmacro %}{% call render_dialog('Hello World') %}This is a simple dialog rendered by using a macro anda call block.{% endcall %}
还可以将参数传回调用块。这使得它可作为循环的替代品。一般来说,调用块的工作方式与没有名称的宏完全相同。
下面是如何使用带参数的调用块的示例:
xxxxxxxxxx{% macro dump_users(users) -%}<ul>{%- for user in users %}<li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>{%- endfor %}</ul>{%- endmacro %}{% call(user) dump_users(list_of_user) %}<dl><dt>Realname</dt><dd>{{ user.realname|e }}</dd><dt>Description</dt><dd>{{ user.description }}</dd></dl>{% endcall %}
过滤器部分允许您在模板数据块上应用常规 Jinja 过滤器。只需将代码包装在特殊filter部分中:
xxxxxxxxxx{% filter upper %}This text becomes uppercase{% endfilter %}
接受参数的过滤器可以像这样调用:
xxxxxxxxxx{% filter center(100) %}Center this{% endfilter %}
在代码块内,您还可以为变量赋值。顶层(块、宏或循环之外)的赋值会像顶层宏一样从模板中导出,并可由其他模板导入。
作业使用set标签并且可以有多个目标:
xxxxxxxxxx{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}{% set key, value = call_something() %}
作用域行为
请记住,不可能在块内设置变量并让它们显示在块外。这也适用于循环。该规则的唯一例外是未引入范围的 if 语句。因此,以下模板不会执行您可能期望的操作:
xxxxxxxxxx{% set iterated = false %}{% for item in seq %}{{ item }}{% set iterated = true %}{% endfor %}{% if not iterated %} did not iterate {% endif %}
使用 Jinja 语法无法做到这一点。相反,可以使用替代结构,例如循环 else 块或特殊loop 变量:
xxxxxxxxxx{% for item in seq %}{{ item }}{% else %}did not iterate{% endfor %}
从 2.10 版开始,可以使用允许跨范围传播更改的命名空间对象来处理更复杂的用例:
xxxxxxxxxx{% set ns = namespace(found=false) %}{% for item in items %}{% if item.check_something() %}{% set ns.found = true %}{% endif %}* {{ item.title }}{% endfor %}Found item having something: {{ ns.found }}
请注意,标签obj.attr中的符号set仅允许用于命名空间对象;尝试在任何其他对象上分配属性都会引发异常。
可以将其用作set块,将块的内容分配给变量。这可用于创建多行字符串,因为 Jinja 不支持 Python 的三重引号 ( """, ''')。
您不需要使用等号和值,而只需写下变量名称以及捕获之前的所有内容。{% endset %}
xxxxxxxxxx{% set navigation %}<li><a href="/">Index</a><li><a href="/downloads">Downloads</a>{% endset %}
应用于变量名称的过滤器将应用于块的内容。
xxxxxxxxxx{% set reply | wordwrap %}You wrote:{{ message }}{% endset %}
标记extends可用于将一个模板扩展为另一个模板。extends一个文件中可以有多个标记,但一次只能执行其中一个。
请参阅上面有关模板继承的部分。
块用于继承,同时充当占位符和替换。它们在 模板继承部分有详细说明。
该include标签渲染另一个模板并将结果输出到当前模板中。
xxxxxxxxxx{% include 'header.html' %}Body goes here.{% include 'footer.html' %}
默认情况下,包含的模板可以访问当前模板的上下文。使用来改用单独的上下文。 也是有效的,但是是默认行为。请参阅 导入上下文行为。without context``with context
被包含的模板可以extend覆盖另一个模板中的块。但是,当前模板不能覆盖被包含的模板输出的任何块。
如果模板不存在,则用于忽略该语句。它必须放在上下文可见性语句之前。ignore missing
xxxxxxxxxx{% include "sidebar.html" without context %}{% include "sidebar.html" ignore missing %}{% include "sidebar.html" ignore missing with context %}{% include "sidebar.html" ignore missing without context %}
如果给出了模板列表,则将按顺序尝试每个模板,直到有一个模板不存在。这可以与忽略一起使用,如果模板不存在。ignore missing
xxxxxxxxxx{% include ['page_detailed.html', 'page.html'] %}{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
还可以将具有模板名称或模板对象的变量传递给语句。
Jinja 支持将常用代码放入宏中。这些宏可以进入不同的模板并从那里导入。这与 Python 中的 import 语句类似。重要的是要知道导入会被缓存,并且导入的模板默认无法访问当前模板变量,只能访问全局变量。有关导入和包含的上下文行为的更多详细信息,请参阅导入上下文行为。
导入模板有两种方式。您可以将完整模板导入变量,也可以从中请求特定的宏/导出变量。
假设我们有一个渲染表单的辅助模块(称为forms.html):
xxxxxxxxxx{% macro input(name, value='', type='text') -%}<input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">{%- endmacro %}{%- macro textarea(name, value='', rows=10, cols=40) -%}<textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols}}">{{ value|e }}</textarea>{%- endmacro %}
访问模板变量和宏的最简单、最灵活的方法是将整个模板模块导入到变量中。这样,您就可以访问属性:
xxxxxxxxxx{% import 'forms.html' as forms %}<dl><dt>Username</dt><dd>{{ forms.input('username') }}</dd><dt>Password</dt><dd>{{ forms.input('password', type='password') }}</dd></dl><p>{{ forms.textarea('comment') }}</p>
或者,您可以将模板中的特定名称导入到当前命名空间:
xxxxxxxxxx{% from 'forms.html' import input as input_field, textarea %}<dl><dt>Username</dt><dd>{{ input_field('username') }}</dd><dt>Password</dt><dd>{{ input_field('password', type='password') }}</dd></dl><p>{{ textarea('comment') }}</p>
以一个或多个下划线开头的宏和变量是私有的,不能被导入。
默认情况下,包含的模板会传递当前上下文,而导入的模板则不会。原因是导入与包含不同,会被缓存;因为导入通常仅用作包含宏的模块。
可以明确改变此行为:通过向 import/include 指令添加 或,当前上下文可以传递给模板并自动禁用缓存。with context``without context
以下有两个示例:
xxxxxxxxxx{% from 'forms.html' import input with context %}{% include 'header.html' without context %}
笔记
在 Jinja 2.0 中,传递给包含模板的上下文不包含模板中定义的变量。事实上,这是行不通的:
xxxxxxxxxx{% for box in boxes %}{% include "render_box.html" %}{% endfor %}
所 包含的模板在 Jinja 2.0 中render_box.html无法访问box。从 Jinja 2.1 开始,render_box.html 可以访问。
Jinja 允许在任何地方使用基本表达式。这些表达式的工作方式与常规 Python 非常相似;即使您不使用 Python,也应该能够熟练使用。
最简单的表达式形式是文字。文字是 Python 对象(例如字符串和数字)的表示。存在以下文字:
"Hello World"
两个双引号或单引号之间的所有内容都是字符串。每当您需要模板中的字符串时(例如作为函数调用和过滤器的参数,或者只是扩展或包含模板),它们都很有用。
42/123_456
整数是没有小数部分的整数。可以使用“_”字符来分隔组以提高可读性。
42.23/ 42.1e2/123_456.789
浮点数可以使用“.”作为小数点符号来书写。浮点数也可以用科学计数法书写,使用大写或小写“e”来表示指数部分。可以使用“_”字符来分隔组以提高可读性,但不能用于指数部分。
['list', 'of', 'objects']
两个括号之间的所有内容都是列表。列表对于存储要迭代的顺序数据非常有用。例如,您可以使用列表和元组轻松创建链接列表(以及使用 for 循环):<ul> {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'), ('downloads.html', 'Downloads')] %} <li><a href="{{ href }}">{{ caption }}</a></li> {% endfor %} </ul>
('tuple', 'of', 'values')
元组类似于列表,无法修改(“不可变”)。如果元组只有一个项,则后面必须跟一个逗号 ( ('1-tuple',))。元组通常用于表示两个或多个元素的项。有关更多详细信息,请参阅上面的列表示例。
{'dict': 'of', 'key': 'and', 'value': 'pairs'}
Python 中的字典是一种将键和值组合在一起的结构。键必须是唯一的,并且始终只有一个值。字典很少用于模板;它们在一些罕见的情况下很有用,例如xmlattr() 过滤器。
true/false
true永远是真,也false永远是假。
笔记
特殊常量true、false和none确实是小写的。因为这在过去会造成混淆(True用于扩展为未定义的变量,该变量被认为是错误的),所以现在这三个也可以用标题大小写(True、False和None)来书写。但是,为了保持一致性(所有 Jinja 标识符都是小写的),您应该使用小写版本。
Jinja 允许您使用值进行计算。这在模板中很少有用,但是为了完整性而存在的。支持以下运算符:
+
将两个对象相加。通常对象是数字,但如果都是字符串或列表,则可以用这种方式连接它们。但是,这不是连接字符串的首选方法!对于字符串连接,请查看运算符~。 是。{{ 1 + 1 }}``2
-
用第一个数字减去第二个数字。 是。{{ 3 - 2 }}``1
/
将两个数字相除。返回值将是一个浮点数。 是。{{ 1 / 2 }}``{{ 0.5 }}
//
将两个数相除并返回截断的整数结果。 是。{{ 20 // 7 }}``2
%
计算整数除法的余数。 是。{{ 11 % 7 }}``4
*
将左操作数与右操作数相乘。 将返回。这也可以用于多次重复字符串。 将打印 80 个等号的条。{{ 2 * 2 }}``4``{{ '=' * 80 }}
**
将左操作数提升为右操作数的幂。 将返回。{{ 2**3 }}``8与 Python 不同,链式 pow 是从左到右进行求值的。 求值方式与 Jinja 相同,但求值方式与 Python 相同。 在 Jinja 中使用括号明确说明您想要的顺序。 通常,最好在 Python 中进行扩展数学运算并将结果传递给, 而不是在模板中执行。{{ 3**3**3 }}``(3**3)**3``3**(3**3)``render如果可以引入升级路径,此行为将来可能会改变以匹配 Python。
==
比较两个对象是否相等。
!=
比较两个对象是否不相等。
>
true如果左侧大于右侧。
>=
true如果左侧大于或等于右侧。
<
true如果左侧低于右侧。
<=
true如果左侧低于或等于右侧。
对于if语句、for过滤和if表达式,组合多个表达式会很有用。
and
对于,如果为假,则值为,否则。在布尔上下文中,这将被视为两个操作数均为真。x and y``x``x``y``True
or
对于,如果为真,则值为,否则。在布尔上下文中,这将被视为至少有一个操作数为真。x or y``x``x``y``True
not
对于,如果为假,则值为,否则 。not x``x``True``False优先使用否定is和in中缀表示法: 而不是;而不是。所有其他表达式都需要前缀表示法: foo is not bar``not foo is bar``foo not in bar``not foo in bar``not (foo and bar).
(expr)
括号将表达式分组。这用于更改求值顺序,或使长表达式更易于阅读或减少歧义。
下列运算符非常有用,但不属于其他两类:
in
执行序列/映射包含测试。如果左操作数包含在右操作数中,则返回 true。 例如,将返回 true。{{ 1 in [1, 2, 3] }}
is
进行测试。
|(管道、竖杆)
应用过滤器。
~(波浪号)
将所有操作数转换为字符串并将它们连接起来。{{ "Hello " ~ name ~ "!" }}将返回(假设name设置为'John')。Hello John!
()
调用一个可调用函数:。在括号内,你可以使用位置参数和关键字参数,就像在 Python 中一样:{{ post.render() }}``{{ post.render(user, full=true) }}。
./[]
获取对象的属性。(请参阅变量)
也可以使用内联if表达式。在某些情况下,内联表达式很有用。例如,如果定义了变量,则可以使用它从一个模板扩展,否则从默认布局模板扩展:
xxxxxxxxxx{% extends layout_template if layout_template is defined else 'default.html' %}
一般语法是。<do something> if <something is true> else <do something else>
该else部分是可选的。如果未提供,则 else 块会隐式评估为一个Undefined对象(无论undefined 环境中设置为何):
xxxxxxxxxx{{ "[{}]".format(page.title) if page.title }}
您还可以使用变量类型上定义的任何方法。方法调用返回的值用作表达式的值。下面是一个使用字符串上定义的方法的示例(其中page.title是字符串):
xxxxxxxxxx{{ page.title.capitalize() }}
这适用于用户定义类型的方法。例如,如果 f类型的变量上定义Foo了一个方法bar,则可以执行以下操作:
xxxxxxxxxx{{ f.bar(value) }}
操作符方法也按预期工作。例如,%为字符串实现 printf 样式:
xxxxxxxxxx{{ "Hello, %s!" % name }}
尽管您应该更喜欢.format这种情况的方法(在呈现模板的上下文中有点不自然):
xxxxxxxxxx{{ "Hello, {}!".format(name) }}
jinja-filters. abs ( x , / )
返回参数的绝对值。
jinja-filters. attr ( obj : Any , name : str ) → jinja2.runtime.Undefined | Any
获取对象的属性。 foo|attr("bar")工作原理 foo.bar就像总是返回属性而不查找项目一样。请参阅订阅说明以了解更多详细信息。
jinja-filters. batch(值:'t.Iterable[V]' ,行数:int , fill_with :'t.Optional[V]' = None ) → 't.Iterator[t.List[V]]'
批量处理项目的过滤器。它的工作原理与slice 反向操作非常相似。它返回具有给定项目数量的列表列表。如果您提供第二个参数,则用于填充缺失的项目。请参阅此示例:<table> {%- for row in items|batch(3, ' ') %} <tr> {%- for column in row %} <td>{{ column }}</td> {%- endfor %} </tr> {%- endfor %} </table>
jinja-filters. capitalize ( s : str ) → str
将值大写。第一个字符大写,其他字符小写。
jinja-filters.center(值*:str,宽度:int* = 80)→ str¶
将值置于给定宽度的字段的中心。
jinja - filters.default(值*:V*, default_value *:V* = ', boolean :**bool = False)→ V¶
如果值未定义,它将返回传递的默认值,否则返回变量的值:{{ my_variable|default('my_variable is not defined') }} ``my_variable如果变量已定义,则输出 的值,否则输出。如果要对计算结果为 false 的变量使用默认值,则必须将第二个参数设置为:'my_variable is not defined'``true``{{ ''|default('the string was empty', true) }}变更日志](https://jinja.palletsprojects.com/en/stable/api/#jinja2.Environment)[[](https://jinja.palletsprojects.com/en/stable/api/#jinja2.UndefinedError)别名:d
jinja-filters. dictsort ( value : Mapping [ K , V ] , case_sensitive : bool = False , by : 'te.Literal["key", "value"]' = 'key' , reverse : bool = False ) → List [ Tuple [ K , V ] ]
对字典进行排序并生成(键,值)对。Python 字典的显示顺序可能不符合您的要求,因此请先对其进行排序。{% for key, value in mydict|dictsort %} sort the dict by key, case insensitive {% for key, value in mydict|dictsort(reverse=true) %} sort the dict by key, case insensitive, reverse order {% for key, value in mydict|dictsort(true) %} sort the dict by key, case sensitive {% for key, value in mydict|dictsort(false, 'value') %} sort the dict by value, case insensitive
jinja-filters. escape ( s : 't.Any' , / ) → 'Markup'
将字符串中的字符&、<、>、'和替换为 HTML 安全序列。如果您需要在 HTML 中显示可能包含此类字符的文本,请使用此选项。"如果对象有一个__html__方法,则调用该方法并且假定返回值对于 HTML 来说已经是安全的。参数:s – 要转换为字符串并转义的对象。返回:Markup带有转义文本的字符串。别名:e
- filters.filesizeformat (*值:str* | float | int,二进制:bool = False)→ str¶
将值格式化为“人类可读”的文件大小(即 13 kB、4.1 MB、102 字节等)。默认使用十进制前缀(Mega、Giga 等),如果第二个参数设置为True二进制前缀(Mebi、Gibi)。
jinja-filters.first(seq :**'t.Iterable[V]')→ 't.Union[V, Undefined] '
返回序列的第一个项目。
jinja-filters. float(值:Any ,默认值:float = 0.0 ) → float
将值转换为浮点数。如果转换无效,它将返回0.0。您可以使用第一个参数覆盖此默认值。
jinja-filters. forceescape (值: 't.Union[str, HasHTML]' ) → markupsafe.Markup
强制 HTML 转义。这可能会使变量转义次数增加一倍。
- filters.format(值*:str*, * args :**Any, kwargs :**Any)→ str¶
将给定的值应用于printf 样式的格式字符串,如 。string % values``{{ "%s, %s!"|format(greeting, name) }} Hello, World! ``%大多数情况下,使用操作符或应该更方便、更有效 str.format()。{{ "%s, %s!" % (greeting, name) }} {{ "{}, {}!".format(greeting, name) }}
jinja-filters. groupby (值: 't.Iterable[V]' ,属性: str | int ,默认值: Any | None = None ,区分大小写: bool = False ) → 't.List[_GroupTuple]'
使用 Python 的 按照属性对对象序列进行分组 itertools.groupby()。属性可以使用点符号进行嵌套访问,例如"address.city"。与 Python 的 不同groupby,值首先进行排序,因此每个唯一值仅返回一个组。User例如,具有某个属性的对象列表city可以按组呈现。在此示例中,grouper指的是city组的值。<ul>{% for city, items in users|groupby("city") %} <li>{{ city }} <ul>{% for user in items %} <li>{{ user.name }} {% endfor %}</ul> </li> {% endfor %}</ul> ``groupby产生 的命名元组,可以用来代替上面的元组解包。是属性的值,是具有该值的项目。(grouper, list)``grouper``list``<ul>{% for group in users|groupby("city") %} <li>{{ group.grouper }}: {{ group.list|join(", ") }} {% endfor %}</ul> ``default如果列表中的对象没有给定的属性,您可以指定要使用的值。<ul>{% for city, items in users|groupby("city", default="NY") %} <li>{{ city }}: {{ items|map(attribute="name")|join(", ") }}</li> {% endfor %}</ul>与过滤器一样sort(),排序和分组默认不区分大小写。key每个组的 都将具有该组值中第一个项目的大小写。例如,如果用户列表有 城市,则“CA”组将有两个值。可以通过传递 来禁用此功能 。["CA", "NY", "ca"]``case_sensitive=True在 3.1 版更改:添加了case_sensitive参数。排序和分组默认不区分大小写,与其他进行比较的过滤器相匹配。变更日志``
jinja-filters. indent ( s : str , width : int | str = 4 , first : bool = False , blank : bool = False ) → str
返回字符串的副本,每行缩进 4 个空格。默认情况下,第一行和空行不缩进。参数:width – 缩进的空格数或字符串。first – 不要跳过缩进第一行。blank – 不要跳过缩进空行。变更日志``````
jinja-filters. int (值:Any ,默认值:int = 0 ,基数:int = 10 ) → int
将值转换为整数。如果转换无效,它将返回0。您可以使用第一个参数覆盖此默认值。您还可以在第二个参数中覆盖默认基数 (10),它处理带有前缀的输入,例如 0b、0o 和 0x,分别表示基数 2、8 和 16。对于十进制数和非字符串值,基数将被忽略。
jinja-filters. items(值:Mapping [ K , V ] | jinja2.runtime.Undefined ) → Iterator [ Tuple [ K , V ] ]
返回映射项上的迭代器。(key, value)``x|items与 相同x.items(),除非x未定义,则返回空迭代器。.items()如果您希望使用另一种编程语言中没有映射类型方法的 Jinja 实现来呈现模板,则此过滤器很有用。<dl> {% for key, value in my_dict|items %} <dt>{{ key }} <dd>{{ value }} {% endfor %} </dl>在 3.1 版本中添加。
-filters.join(值:Iterable [ Any ], d :**str = ' ',属性:str **| int **| NoneType = None)→ str¶
返回序列中字符串的连接结果,元素之间的分隔符默认为空字符串,您可以使用可选参数定义它:{{ [1, 2, 3]|join('|') }} -> 1|2|3 {{ [1, 2, 3]|join }} -> 123还可以连接对象的某些属性:{{ users|join(', ', attribute='username') }}变更日志``
jinja-filters. last ( seq : 't.Reversible[V]' ) → 't.Union[V, Undefined]'
返回序列的最后一项。注意:不适用于生成器。您可能需要将其明确转换为列表:{{ data | selectattr('name', '==', 'Jinja') | list | last }}
filters.length(obj, /)¶
返回容器中的物品数量。别名:count
jinja-filters.list(值*:'t.Iterable[V]')* → ' t.List[V]'
将值转换为列表。如果是字符串,则返回的列表将是字符列表。
jinja-filters. lower ( s : str ) → str
将值转换为小写。
jinja-filters.map (*值:Iterable* [ Any ], * args *:Any*, kwargs :**Any)→ Iterable [ Any ]**
对一系列对象应用过滤器或查找属性。这在处理对象列表但您实际上只对其中的某个值感兴趣时很有用。基本用法是映射属性。假设您有一个用户列表,但您只对用户名列表感兴趣:Users on this page: {{ users|map(attribute='username')|join(', ') }} ``default如果列表中的对象没有给定的属性,您可以指定要使用的值。{{ users|map(attribute="username", default="Anonymous")|join(", ") }}或者,您可以通过传递过滤器的名称和随后的参数来让它调用过滤器。一个很好的例子是将文本转换过滤器应用于序列:Users on this page: {{ titles|map('lower')|join(', ') }}类似于生成器理解,例如:(u.username for u in users) (getattr(u, "username", "Anonymous") for u in users) (do_lower(x) for x in titles)变更日志``
jinja-filters.max(值*:'t.Iterable[V]'*, case_sensitive *:bool* = False,属性:str **| int **| NoneType = None)→ 't.Union[V, Undefined] '
返回序列中的最大项目。{{ [1, 2, 3]|max }} -> 3参数:case_sensitive – 将大写和小写字符串视为不同的字符串。属性– 获取此属性最大值的对象。
jinja-filters.min(值*:'t.Iterable[V]'*, case_sensitive *:bool* = False,属性:str **| int **| NoneType = None)→ 't.Union[V, Undefined] '
返回序列中的最小项。{{ [1, 2, 3]|min }} -> 1参数:case_sensitive – 将大写和小写字符串视为不同的字符串。属性– 获取具有此属性的最小值的对象。
jinja-过滤器。pprint(值:任意 ) → str
漂亮地打印变量。对调试很有用。
jinja - filters.random (*seq:'t.Sequence[V]'*)→ 't.Union[V, Undefined]'
从序列中返回一个随机项目。
jinja - filters.reject (值:**'t.Iterable[V]', * args *:Any* , kwargs :**Any ) → 't.Iterator[V]'
通过对每个对象应用测试来过滤一系列对象,并拒绝测试成功的对象。如果没有指定测试,则每个对象将被评估为布尔值。使用示例:{{ numbers|reject("odd") }}类似于生成器理解,例如:(n for n in numbers if not test_odd(n))变更日志
jinja-filters.rejectattr(值**: ' t.Iterable [V]', * args *:Any*, kwargs :**Any)→ 't.Iterator[V]'
通过对每个对象的指定属性应用测试来过滤一系列对象,并拒绝测试成功的对象。如果没有指定测试,则属性的值将被评估为布尔值。{{ users|rejectattr("is_active") }} {{ users|rejectattr("email", "none") }}类似于生成器理解,例如:(user for user in users if not user.is_active) (user for user in users if not test_none(user.email))变更日志
返回值的副本,其中所有出现的子字符串都被替换为新字符串。第一个参数是应替换的子字符串,第二个参数是替换字符串。如果count给出了可选的第三个参数,则仅 count替换第一次出现的内容:{{ "Hello World"|replace("Hello", "Goodbye") }} -> Goodbye World {{ "aaaaargh"|replace("a", "d'oh, ", 2) }} -> d'oh, d'oh, aaargh
jinja-过滤器。反向(值:str | Iterable [ V ] ) → str |可迭代[ V ]
反转对象或返回以相反方向对其进行迭代的迭代器。
jinja-filters. round (值: float ,精度: int = 0 ,方法: 'te.Literal["common", "ceil", "floor"]' = 'common' ) → float
将数字四舍五入到给定的精度。第一个参数指定精度(默认为0),第二个参数指定四舍五入方法:'common'向上或向下舍入'ceil'总是四舍五入'floor'总是向下舍入如果您未指定,'common'则使用一种方法。{{ 42.55|round }} -> 43.0 {{ 42.55|round(1, 'floor') }} -> 42.5请注意,即使四舍五入到 0 精度,也会返回浮点数。如果您需要实数整数,请通过管道将其传递int:{{ 42.55|round|int }} -> 43
jinja-filters.safe (*value* :**str)→ markupsafe.Markup
将该值标记为安全的,这意味着在启用自动转义的环境中,该变量将不会被转义。
jinja-filters. select(值:'t.Iterable[V]' , * args :Any , ** kwargs :Any ) → 't.Iterator[V]'
通过对每个对象应用测试来过滤一系列对象,并仅选择测试成功的对象。如果没有指定测试,则每个对象将被评估为布尔值。使用示例:{{ numbers|select("odd") }} {{ numbers|select("odd") }} {{ numbers|select("divisibleby", 3) }} {{ numbers|select("lessthan", 42) }} {{ strings|select("equalto", "mystring") }}类似于生成器理解,例如:(n for n in numbers if test_odd(n)) (n for n in numbers if test_divisibleby(n, 3))变更日志
jinja-filters. selectattr ( value : 't.Iterable[V]' , * args : Any , ** kwargs : Any ) → 't.Iterator[V]'
通过对每个对象的指定属性应用测试来过滤一系列对象,并仅选择测试成功的对象。如果没有指定测试,则属性的值将被评估为布尔值。使用示例:{{ users|selectattr("is_active") }} {{ users|selectattr("email", "none") }}类似于生成器理解,例如:(user for user in users if user.is_active) (user for user in users if test_none(user.email))变更日志
jinja-filters.slice(值:'t.Collection[V]', slices :int,**fill_with :**'t.Optional[V]' = None)→ 't.Iterator[t.List[V]] '
对迭代器进行切片并返回包含这些项目的列表。如果您想创建一个包含三个代表列的 ul 标签的 div,这将非常有用:<div class="columnwrapper"> {%- for column in items|slice(3) %} <ul class="column-{{ loop.index }}"> {%- for item in column %} <li>{{ item }}</li> {%- endfor %} </ul> {%- endfor %} </div>如果向其传递第二个参数,它将用于填充最后一次迭代中的缺失值。
jinja-filters.sort(值*:'t.Iterable[V]'* ,reverse:bool = False *,case_sensitive* :**bool = False ,属性:**str | int | NoneType **= None **) → ' t.List [ V ]'
使用 Python 的 对可迭代对象进行排序sorted()。{% for city in cities|sort %} ... {% endfor %}参数:反向– 按降序排序,而不是升序排序。case_sensitive – 对字符串进行排序时,分别对大小写进行排序。属性– 对对象或字典进行排序时,要按其排序的属性或键。可以使用点符号,例如"address.city"。可以是属性列表,例如"age,name"。排序是稳定的,它不会改变相等元素的相对顺序。这使得可以对不同的属性和顺序进行链式排序。{% for user in users|sort(attribute="name") |sort(reverse=true, attribute="age") %} ... {% endfor %}当所有属性的方向相同时,作为链接的快捷方式,传递以逗号分隔的属性列表。{% for user in users|sort(attribute="age,name") %} ... {% endfor %}变更日志``````
jinja-filters.string ( s : ' t.Any ' , / ) → 'str'
如果对象尚未转换为字符串,则将其转换为字符串。这将保留Markup字符串,而不是将其转换回基本字符串,因此它仍将被标记为安全,并且不会再次被转义。>>> value = escape("<User 1>") >>> value Markup('<User 1>') >>> escape(str(value)) Markup('<User 1>') >>> escape(soft_str(value)) Markup('<User 1>')
jinja-filters. striptags (值: 't.Union[str, HasHTML]' ) → str
删除 SGML/XML 标签并用一个空格替换相邻的空格。
jinja-filters. sum ( iterable : 't.Iterable[V]' , attribute : str | int | NoneType = None , start : V = 0 ) → V
返回数字序列与参数“start”值(默认为 0)之和。当序列为空时,返回 start。也可以只总结某些属性:Total: {{ items|sum(attribute='price') }}变更日志````
- filters.title(s**:**str)→ str¶
返回值的标题形式版本。即单词将以大写字母开头,其余所有字符均为小写。
jinja-filters. tojson (值: Any , indent : int | None = None ) → markupsafe.Markup
将对象序列化为 JSON 字符串,并将其标记为可在 HTML 中安全呈现。此过滤器仅适用于 HTML 文档。返回的字符串可以安全地呈现在 HTML 文档和 <script>标签中。例外情况是双引号中的 HTML 属性;请使用单引号或|forceescape 过滤器。参数:value – 要序列化为 JSON 的对象。indent –indent传递给的参数dumps,用于漂亮地打印值。变更日志
jinja filters.trim(值:str, chars :str | None = None**)**→ str¶
删除前导和尾随字符,默认为空格。
jinja-filters. truncate ( s : str , length : int = 255 , killwords : bool = False , end : str = '...' , leeway : int | None = None ) → str
返回字符串的截断副本。长度由第一个参数指定,默认为255。如果第二个参数为,则true过滤器将按长度截断文本。否则,它将丢弃最后一个单词。如果文本确实被截断,它将附加一个省略号 ( "...")。如果您想要不同的省略号,"..."可以使用第三个参数指定它。长度仅超出第四个参数中给出的容差范围的字符串将不会被截断。{{ "foo bar baz qux"|truncate(9) }} -> "foo..." {{ "foo bar baz qux"|truncate(9, True) }} -> "foo ba..." {{ "foo bar baz qux"|truncate(11) }} -> "foo bar baz qux" {{ "foo bar baz qux"|truncate(11, False, '...', 0) }} -> "foo bar..."新版 Jinja 的默认余地为 5,之前为 0,但可以全局重新配置。
jinja-filters.unique (值:**'t.Iterable[V]', case_sensitive :**bool = False,属性:str | int **| NoneType = None)→ 't.Iterator[V] '
返回给定可迭代对象中唯一项的列表。{{ ['foo', 'bar', 'foobar', 'FooBar']|unique|list }} -> ['foo', 'bar', 'foobar']唯一项的产生顺序与传递给过滤器的可迭代对象中第一次出现的顺序相同。参数:case_sensitive – 将大写和小写字符串视为不同的字符串。属性— 过滤具有此属性唯一值的对象。
jinja-filters. upper ( s : str ) → str
将值转换为大写。
jinja-filters. urlencode ( value : str | Mapping [ str , Any ] | Iterable [ Tuple [ str , Any ] ] ) → str
使用 UTF-8 来引用 URL 路径或查询中使用的数据。urllib.parse.quote()当给定一个字符串、urllib.parse.urlencode()一个字典或可迭代对象时的基本包装器。参数:value – 要引用的数据。将直接引用字符串。将以查询字符串的形式连接成一个字典或可迭代对象。(key, value)给定字符串时,“/” 不带引号。HTTP 服务器在路径中同等对待“/”和“%2F”。如果您需要带引号的斜线,请使用 过滤器。|replace("/", "%2F")变更日志
jinja-filters. urlize ( value : str , trim_url_limit : int | None = None , nofollow : bool = False , target : str | None = None , rel : str | None = None , extra_schemes : Iterable [ str ] | None = None ) → str
将文本中的 URL 转换为可点击的链接。在某些情况下,这可能无法识别链接。通常,更全面的格式化程序(例如 Markdown 库)是更好的选择。适用于http://、https://、www.、mailto:和电子邮件地址。带尾标点符号(句号、逗号、右括号)和前导标点符号(左括号)的链接均可识别,但不包括标点符号。不识别包含标题字段的电子邮件地址(例如 mailto:address@example.com?cc=copy@example.com)。参数:值– 包含要链接的 URL 的原始文本。trim_url_limit – 将显示的 URL 值缩短至此长度。nofollowrel=nofollow –向链接添加属性。目标– 将target属性添加到链接。relrel –向链接添加属性。extra_schemes – 除了默认行为外,还识别以这些方案开头的 URL。默认为 env.policies["urlize.extra_schemes"],即默认无额外方案。变更日志````````
filters.wordcount ( s : str ) → int ¶
计算该字符串中的单词数。
jinja-filters. wordwrap ( s : str , width : int = 79 , break_long_words : bool = True , wrapstring : str | None = None , break_on_hyphens : bool = True ) → str
将字符串换行到给定的宽度。现有的换行符将被视为段落,需要单独换行。参数:s – 要换行的原始文本。width – 换行的最大长度。break_long_words – 如果单词长度超过width,则将其分行。break_on_hyphens – 如果单词包含连字符,则可能会将其分成多行。wrapstring – 连接每个换行的字符串。默认为 Environment.newline_sequence。变更日志````
jinja-filters. xmlattr ( d : Mapping [ str , Any ] , autospace : bool = True ) → str
根据字典中的项目创建 SGML/XML 属性字符串。既不是none也不是的值undefined会自动转义,从而安全地允许不受信任的用户输入。用户输入不应用作此过滤器的键。如果任何键包含空格、/斜线、>大于号或=等号,则此操作会失败并显示ValueError。无论如何,用户输入都不应用作此过滤器的键,或者必须先单独验证。<ul{{ {'class': 'my_list', 'missing': none, 'id': 'list-%d'|format(variable)}|xmlattr }}> ... </ul>结果如下:<ul class="my_list" id="list-42"> ... </ul>如您所见,如果过滤器返回了某些内容,它会自动在项目前面添加一个空格,除非第二个参数为假。在 3.1.4 版更改:不允许使用/斜线、>大于号或等号的键。=在 3.1.3 版更改:不允许使用带空格的键。
jinja-tests. boolean ( value : Any ) → bool
如果对象是布尔值,则返回 true。变更日志
tests.callable(obj, /)¶
返回对象是否可调用(即某种函数)。请注意,类是可调用的,具有 call() 方法的类的实例也是如此。
jinjatests.defined(值*:*Any)→ bool¶
如果变量已定义,则返回 true:{% if variable is defined %} value of variable: {{ variable }} {% else %} variable is not defined {% endif %}查看default()过滤器以了解设置未定义变量的简单方法。
jinja-tests. divisibleby ( value : int , num : int ) → bool
检查一个变量是否能被某个数字整除。
jinja-tests. eq ( a , b , / )
与 a == b 相同。别名:==,equalto
jinja-tests. escaped ( value : Any ) → bool
检查该值是否被转义。
jinja-tests. even ( value : int ) → bool
如果变量为偶数,则返回 true。
jinja-tests. false ( value : Any ) → bool
如果对象为 False,则返回 True。变更日志
- tests.filter(值*:*str)→ bool¶
根据名称检查过滤器是否存在。如果过滤器是可选的,则很有用。{% if 'markdown' is filter %} {{ value | markdown }} {% else %} {{ value }} {% endif %}变更日志
jinja-tests. float ( value : Any ) → bool
如果对象是浮点数,则返回 true。变更日志
jinja-tests. ge ( a , b , / )
与 a >= b 相同。别名:>=
jinja-tests. gt ( a , b , / )
与 a > b 相同。别名:>,greaterthan
jinja-tests.in (*值:Any*, seq :**Container [ Any ])→ bool¶**
检查值是否在序列中。变更日志
- tests.integer(值*:*Any)→ bool¶
如果对象是整数,则返回 true。变更日志
jinja-tests. iterable ( value : Any ) → bool
检查是否可以迭代某个对象。
jinja 测试。le ( a , b , / )
与 a <= b 相同。别名:<=
jinja-testslower(value :str ) → bool¶
如果变量是小写的,则返回 true。
jinja-tests. lt ( a , b , / )
与 a < b 相同。别名:<,lessthan
jinja tests.mapping(值*:*Any ) → bool¶
如果对象是映射(字典等),则返回 true。变更日志
jinja-tests. ne ( a , b , / )
与 a != b 相同。别名:!=
jinja-tests. none ( value : Any ) → bool
如果变量为无,则返回 true。
jinja tests.number(值*:*Any ) → bool¶
如果变量是数字,则返回 true。
jinjatests.odd(值*:*int)→ bool¶
如果变量为奇数,则返回 true。
jinja tests.sameas(值:Any,其他**:**Any ) → bool¶
检查一个对象是否指向与另一个对象相同的内存地址:{% if foo.attribute is sameas false %} the foo attribute really is theFalsesingleton {% endif %}
jinja - tests.sequence(值*:*Any)→ bool
如果变量是序列,则返回 true。序列是可迭代的变量。
- tests.string(值**:**Any)→ bool¶
如果对象是字符串,则返回 true。
jinja-tests. test ( value : str ) → bool
根据名称检查测试是否存在。如果测试是可选的,则很有用。{% if 'loud' is test %} {% if value is loud %} {{ value|upper }} {% else %} {{ value|lower }} {% endif %} {% else %} {{ value }} {% endif %}变更日志
jinja-tests. true ( value : Any ) → bool
如果对象为 True,则返回 true。变更日志
jinja tests.undefined(值**: Any ) → bool¶
就像defined(),但反过来。
jinja-tests. upper(值:str ) → bool
如果变量是大写,则返回 true。
默认情况下,以下函数在全局范围内可用:
jinja -globals.range ( [开始, ]停止[,步骤] )
返回一个包含整数等差数列的列表。 返回;start(!)默认为。当给出step时,它指定增量(或减量)。例如,并返回。省略终点!这些正是4个元素列表的有效索引。range(i, j)``[i, i+1, i+2, ..., j-1]``0``range(4)``range(0, 4, 1)``[0, 1, 2, 3]这对于多次重复模板块很有用,例如填充列表。假设列表中有 7 个用户,但您想渲染三个空项以使用 CSS 强制高度:<ul> {% for user in users %} <li>{{ user.username }}</li> {% endfor %} {% for number in range(10 - users|count) %} <li class="empty"><span>...</span></li> {% endfor %} </ul>
jinja - globals.lipsum(n = 5, html = True,最小值**= 20,最大值**= 100)
为模板生成一些 lorem ipsum。默认情况下,会生成五段 HTML,每段 20 到 100 个字。如果 html 为 False,则返回常规文本。这对于生成用于布局测试的简单内容很有用。
jinja-globals. dict ( *items* )
字典文字的一个便捷替代方案。 与 相同。{'foo': 'bar'}``dict(foo='bar')
类 jinja-globals. cycler ( *items )
通过每次产生一个值来循环这些值,然后在到达末尾时重新启动。与 类似loop.cycle,但可以在循环外或多个循环中使用。例如,在列表中呈现文件夹和文件列表,交替为它们赋予“奇数”和“偶数”类。{% set row_class = cycler("odd", "even") %} <ul class="browser"> {% for folder in folders %} <li class="folder {{ row_class.next() }}">{{ folder }} {% endfor %} {% for file in files %} <li class="file {{ row_class.next() }}">{{ file }} {% endfor %} </ul>参数:项目– 每个位置参数将按照每个循环给出的顺序产生。变更日志属性 current返回当前项。相当于下次next()调用时将返回的项。下一个()返回当前项目,然后前进current到下一个项目。重置()将当前项目重置为第一项。
class jinja-globals.joiner ( sep = ' , ' )
一个小助手,可用于“连接”多个部分。连接器会传递一个字符串,每次调用时都会返回该字符串,第一次调用除外(在这种情况下它会返回一个空字符串)。您可以使用它来连接事物:{% set pipe = joiner("|") %} {% if categories %} {{ pipe() }} Categories: {{ categories|join(", ") }} {% endif %} {% if author %} {{ pipe() }} Author: {{ author() }} {% endif %} {% if can_edit %} {{ pipe() }} <a href="?action=edit">Edit</a> {% endif %}变更日志
class jinja-globals. namespace ( ... )
创建一个新容器,允许使用 标签分配属性:{% set %}``{% set ns = namespace() %} {% set ns.foo = 'bar' %}这样做的主要目的是允许将值从循环体内传递到外部范围。初始值可以作为字典、关键字参数或两者提供(与 Python 的dict构造函数行为相同):{% set ns = namespace(found=false) %} {% for item in items %} {% if item.check_something() %} {% set ns.found = true %} {% endif %} * {{ item.title }} {% endfor %} Found item having something: {{ ns.found }}在 3.2 版更改:命名空间属性可以在多个赋值中被分配。变更日志
以下部分涵盖了应用程序可能启用的内置 Jinja 扩展。应用程序还可以提供本文档未涵盖的进一步扩展;在这种情况下,应该有单独的文档来解释所述扩展。
如果启用了i18n 扩展,则可以将模板中的文本标记为可翻译。要将某个部分标记为可翻译,请使用以下 trans块:
xxxxxxxxxx{% trans %}Hello, {{ user }}!{% endtrans %}
块内部不允许有语句,只能有文本和简单的变量标签。
变量标签只能是名称,不能是属性访问、过滤器或其他表达式。要使用表达式,请将其绑定到 trans标签中的名称,以便在块中使用。
xxxxxxxxxx{% trans user=user.username %}Hello, {{ user }}!{% endtrans %}
要绑定多个表达式,请用逗号 ( ,) 分隔每个表达式。
xxxxxxxxxx{% trans book_title=book.title, author=author.name %}This is {{ book_title }} by {{ author }}{% endtrans %}
要使用复数形式,请指定标签分隔的单数和复数形式pluralize。
xxxxxxxxxx{% trans count=list|length %}There is {{ count }} {{ name }} object.{% pluralize %}There are {{ count }} {{ name }} objects.{% endtrans %}
默认情况下,块中的第一个变量用于确定使用单数还是复数形式。如果不正确,请将用于复数的变量指定为 的参数pluralize。
xxxxxxxxxx{% trans ..., user_count=users|length %}...{% pluralize user_count %}...{% endtrans %}
翻译文本块时,空格和换行符会导致翻译字符串难以阅读且容易出错。为了避免这种情况,可以将翻译块标记为已修剪,这将用单个空格替换所有换行符及其周围的空格,并删除前导和尾随空格。
xxxxxxxxxx{% trans trimmed book_title=book.title %}This is {{ book_title }}.You should read it!{% endtrans %}
这会产生翻译文件。This is %(book_title)s. You should read it!
如果全局启用了修剪,notrimmed则可以使用修改器为某个块禁用修剪。
如果翻译取决于消息出现的上下文,则pgettext和npgettext函数将context字符串作为第一个参数,用于选择适当的翻译。要使用标签指定上下文,请在后面提供字符串作为第一个标记。{% trans %}``trans
xxxxxxxxxx{% trans "fruit" %}apple{% endtrans %}{% trans "fruit" trimmed count -%}1 apple{%- pluralize -%}{{ count }} apples{%- endtrans %}
在 3.1 版中添加:可以将上下文传递给trans标签以使用pgettext和 npgettext。
可以使用以下函数翻译表达式中的字符串:
_(message): 的别名gettext。gettext(message):翻译消息。ngettext(singular, plural, n):根据计数变量翻译单数或复数消息。pgettext(context, message):类似gettext(),但根据上下文字符串选择翻译。npgettext(context, singular, plural, n):类似npgettext(),但根据上下文字符串选择翻译。您可以像这样打印翻译的字符串:
xxxxxxxxxx{{ _("Hello, World!") }}
要使用占位符,请使用format过滤器。
xxxxxxxxxx{{ _("Hello, %(user)s!")|format(user=user.username) }}
始终使用关键字参数format,因为其他语言可能不按相同顺序使用单词。
如果激活了新样式 Gettext调用,则使用占位符会更容易。格式化是调用的一部分,gettext而不是使用 format过滤器。
xxxxxxxxxx{{ gettext('Hello World!') }}{{ gettext('Hello %(name)s!', name='World') }}{{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
该函数的格式字符串除了给定的参数外,ngettext还会自动接收计数作为参数。num
如果加载了表达式语句扩展,do则可以使用名为 的标签,其工作方式与正则变量表达式 ( ) 完全相同;只是它不会打印任何内容。这可用于修改列表:{{ ... }}
xxxxxxxxxx{% do navigation.append('a string') %}
如果应用程序启用了循环控制,则可以在循环中使用break和。当达到时,循环终止;如果达到,则停止处理并继续下一次迭代。continue``break``continue
这是一个跳过每个第二项的循环:
xxxxxxxxxx{% for user in users %}{%- if loop.index is even %}{% continue %}{% endif %}...{% endfor %}
同样,第 10 次迭代后停止处理的循环:
xxxxxxxxxx{% for user in users %}{%- if loop.index >= 10 %}{% break %}{% endif %}{%- endfor %}
注意loop.index从 1 开始,并且loop.index0从 0 开始(参见:对于)。
如果启用了调试扩展,则可以使用标签来转储当前上下文以及可用的过滤器和测试。这对于查看模板中可用的内容(无需设置调试器)非常有用。{% debug %}
xxxxxxxxxx<pre>{% debug %}</pre>{'context': {'cycler': <class 'jinja2.utils.Cycler'>,...,'namespace': <class 'jinja2.utils.Namespace'>},'filters': ['abs', 'attr', 'batch', 'capitalize', 'center', 'count', 'd',..., 'urlencode', 'urlize', 'wordcount', 'wordwrap', 'xmlattr'],'tests': ['!=', '<', '<=', '==', '>', '>=', 'callable', 'defined',..., 'odd', 'sameas', 'sequence', 'string', 'undefined', 'upper']}
with 语句可以创建一个新的内部作用域。在此作用域内设置的变量在作用域外不可见。
简而言之:
xxxxxxxxxx{% with %}{% set foo = 42 %}{{ foo }} foo is 42 here{% endwith %}foo is not visible here any longer
因为在作用域的开头设置变量很常见,所以你可以在with语句中执行此操作。以下两个示例是等效的:
xxxxxxxxxx{% with foo = 42 %}{{ foo }}{% endwith %}{% with %}{% set foo = 42 %}{{ foo }}{% endwith %}
这里有一个关于作用域的重要说明。在 Jinja 2.9 之前的版本中,将一个变量引用到另一个变量的行为会产生一些意想不到的后果。特别是,一个变量可以引用在同一个 with 块的开头语句中定义的另一个变量。这导致了清理后的作用域行为出现问题,此后已得到改进。特别是在较新的 Jinja 版本中,以下代码始终 a从块外部引用变量with:
xxxxxxxxxx{% with a={}, b=a.attribute %}...{% endwith %}
在早期的 Jinja 版本中,该b属性将引用第一个属性的结果。如果您依赖此行为,则可以重写它以使用set标签:
xxxxxxxxxx{% with a={} %}{% set b = a.attribute %}{% endwith %}
扩大
在旧版本的 Jinja(2.9 之前)中,需要使用扩展来启用此功能。现在默认启用此功能。
如果您愿意,您可以在模板内部激活或停用自动转义功能。
例子:
xxxxxxxxxx{% autoescape true %}Autoescaping is active within this block{% endautoescape %}{% autoescape false %}Autoescaping is inactive within this block{% endautoescape %}
之后,endautoescape行为就会恢复到之前的状态。
扩大
在旧版本的 Jinja(2.9 之前)中,需要使用扩展来启用此功能。现在默认启用此功能。