导航菜单

  • 1.vector
  • 2.milvus
  • 3.pymilvus
  • 4.rag
  • 5.rag_measure
  • ragflow
  • heapq
  • HNSW
  • cosine_similarity
  • math
  • typing
  • etcd
  • minio
  • collections
  • jieba
  • random
  • beautifulsoup4
  • chromadb
  • sentence_transformers
  • numpy
  • lxml
  • openpyxl
  • PyMuPDF
  • python-docx
  • requests
  • python-pptx
  • text_splitter
  • all-MiniLM-L6-v2
  • openai
  • llm
  • BPETokenizer
  • Flask
  • RAGAS
  • BagofWords
  • langchain
  • Pydantic
  • abc
  • faiss
  • MMR
  • scikit-learn
  • Runnable
  • PromptEngineering
  • dataclasses
  • LaTeX
  • rank_bm25
  • TF-IDF
  • asyncio
  • sqlalchemy
  • fastapi
  • Starlette
  • uvicorn
  • argparse
  • Generic
  • ssl
  • urllib
  • python-dotenv
  • RRF
  • CrossEncoder
  • Lost-in-the-middle
  • Jinja2
  • logger
  • io
  • venv
  • concurrent
  • parameter
  • SSE
  • 1. 核心特性
    • 1.1 模板语法
    • 1.2 变量与过滤器
    • 1.3 控制结构
    • 1.4 模板继承
  • 2. 基本使用示例
    • 2.1 Python 代码
    • 2.2 模板文件 my_template.html
  • 3. 高级功能
    • 3.1 自定义过滤器
    • 3.2 宏(类似于函数)
    • 3.3 包含模板
    • 3.4 空白控制
  • 4. 安全特性
    • 1. 自动转义(Autoescape)
    • 2. |safe 过滤器
    • 3. 手动转义与强制转义
    • 4. 禁用代码执行
    • 5. 配置和过滤器加固
  • 5. 常见应用场景
  • 6. 最佳实践

1. 核心特性 #

Jinja2 是一个用 Python 编写的现代、设计友好的模板引擎。它被广泛用于生成动态内容,特别是在 Web 开发中(如 Flask、Django 的模板系统),但也常用于配置文件生成、邮件模板等场景。

1.1 模板语法 #

Jinja2 的模板语法非常灵活,主要分为三大类:

  • 注释 {# ... #}:用于模板中写说明性文字,不会被渲染到输出结果中。
  • 变量 {{ ... }}:用于插入变量,输出变量的值。变量内容可以是复杂表达式,也能调用对象的属性和方法。
  • 语句/控制结构 {% ... %}:用于流程控制,比如条件判断、循环、继承、宏等。

Jinja2 支持类似 Python 的表达式和语法,能方便地书写模板逻辑。同时,它通过“过滤器”提供对变量的进一步加工处理,如格式化字符串、大小写转换、拼接列表等。

例子说明:

  • {{ user.name|upper }} 会把 user.name 的内容转成大写后输出。
  • {% if items %}...{% endif %} 实现条件渲染。
  • {{ list|join(', ') }} 把列表用逗号拼接成字符串。

Jinja2 模板语法利于前后端分离,书写自然、可读性强,对开发网页、配置文件等极为方便。

{# 注释 #}
{{ 变量 }}           {# 变量输出 #}
{% 语句 %}          {# 控制语句 #}

1.2 变量与过滤器 #

Jinja2 变量是模板中动态数据的载体。模板里通过 {{ ... }} 语法插入变量,变量名由渲染时传入的上下文(dict)决定。支持访问属性、下标、链式取值等。例如:

  • {{ user }} 直接输出变量 user
  • {{ user.name }} 访问对象属性
  • {{ users[0] }} 访问列表元素
  • {{ config["key"] }} 访问字典数据

过滤器(filter)用于对变量做进一步处理,语法为 {{ 变量|过滤器名(参数) }}。常见过滤器:

  • upper/lower:大小写转换。如 {{ name|upper }}
  • default:若变量不存在/值为假,使用默认值。如 {{ name|default('匿名') }}
  • length:获取长度。{{ list|length }}
  • join:拼接序列(列表、元组等)为字符串。如 {{ tags|join(', ') }}
  • replace:字符串替换。{{ text|replace('a', 'b') }}
  • safe:标记内容为 HTML 安全,不会被自动转义

还可以链式使用多个过滤器,如:
{{ username|trim|lower|default('guest') }}

Jinja2 内置几十种过滤器,也可自定义过滤器。

1.3 控制结构 #

Jinja2 的控制结构让模板具备类似 Python 的流程控制能力。主要有三类:

  • 条件判断(if/elif/else)
    用于根据变量或表达式的值选择性地渲染内容。通常语法和 Python 类似。

    {% if score >= 90 %}
        优
    {% elif score >= 60 %}
        及格
    {% else %}
        不及格
    {% endif %}
  • 循环 for
    用于遍历序列(列表、字典、集合等)、生成枚举列表。loop 变量可以辅助获取下标、是否首/尾元素等。

    <ul>
    {% for user in users %}
        <li>{{ loop.index }}. {{ user.name }} ({{ user.email }})</li>
    {% endfor %}
    </ul>
    • loop.index:当前迭代从 1 开始的编号
    • loop.first/loop.last:是否首个/最后一个
    • loop.length:循环总长度
  • 其它结构
    Jinja2 还支持 set(设置变量)、macro(自定义宏/函数)、include(引入子模板)、with 快捷变量传递等。例如:

    {% set welcome = "你好, " + user.name %}
    {{ welcome }}

特别说明:

  • 控制结构必须用 {% ... %} 包裹,不能用 {{ ... }}。
  • if/for 可嵌套使用,符合 Python 语法习惯。
  • 仅在 for 内容无数据时渲染 else 子句(不是 for 循环结束后)。
    {% for item in items %}
      ...
    {% else %}
      暂无内容
    {% endfor %}

这些控制结构大幅提高了模板的灵活性,适用于业务数据展示、条件内容输出、动态生成列表表格等各种场景。

1.4 模板继承 #

Jinja2 的模板继承功能,可以让多个页面共享相同的模板结构(如统一的页眉、页脚、导航栏),仅在部分位置替换各自不同的内容。通过继承机制,提升了模板复用性与可维护性。

  • 基础模板(父模板)
    使用 {% block 块名 %}...{% endblock %} 声明可被子模板替换或填充的区域。通常基础模板用于定义通用布局结构,例如网站的整体页面框架。

  • 子模板
    用 {% extends "父模板.html" %} 指定继承的父模板,然后用 {% block %} 替换(重写)父模板中对应的内容块。

示例说明:

  1. base.html(基础模板)

    <!DOCTYPE html>
    <html>
    <head>
        <title>{% block title %}我的网站{% endblock %}</title>
    </head>
    <body>
        <header>
            <h1>网站头部</h1>
        </header>
        <nav>
            <!-- 导航菜单 -->
        </nav>
        <main>
            {% block content %}{% endblock %}
        </main>
        <footer>
            &copy; 2024 示例公司
        </footer>
    </body>
    </html>
  2. child.html(子模板,继承 base.html)

    {% extends "base.html" %}
    {% block title %}个人中心{% endblock %}
    {% block content %}
        <h2>欢迎回来,{{ user.name }}</h2>
        <p>这里是您的个人信息页面。</p>
    {% endblock %}
  • 这样,子模板自动获得父模板的整体结构(头部、导航、页脚),只需关心填充 title 和 content 的内容,极大提升模板的复用性和开发效率。
  • 可以有多个 {% block %},允许不同页面按需仅覆盖局部区域,不被重写的块会显示父模板原内容。

2. 基本使用示例 #

Jinja2 模板的基本用法非常简单,常见的步骤如下:

  1. 模板定义

    • 可以用字符串直接创建模板,也可以从文件加载 HTML/Jinja2 文件作为模板。
  2. 数据渲染

    • 使用 render() 方法,把准备好的变量/字典传给模板,生成最终的 HTML 字符串。
  3. 文件加载典型目录结构

    • 实践中模板通常放在一个 templates/ 文件夹,通过 FileSystemLoader 加载。

示例流程(推荐实际尝试):

  • 直接渲染字符串模板

    # 导入Jinja2中用于模板渲染的Template类
    from jinja2 import Template
    
    # 创建一个模板对象,模板内容中用{{ name }}占位
    template = Template("你好,{{ name }}!")
    # 使用render方法将变量name的值传入模板,生成最终字符串
    html = template.render(name="小明")
    # 输出渲染后的字符串结果
    print(html)  # 输出:你好,小明!
  • 渲染文件模板
    假设有 templates/hello.html:

    <h1>Hi, {{ username }}!</h1>

    加载与渲染:

    # 导入 Jinja2 的 Environment 和 FileSystemLoader,用于环境配置和模板文件加载
    from jinja2 import Environment, FileSystemLoader
    
    # 创建一个模板环境,指定模板文件夹位置为 "templates"
    env = Environment(loader=FileSystemLoader("templates"))
    # 加载名为 "hello.html" 的模板文件
    template = env.get_template("hello.html")
    # 使用 render 方法传入变量 username,渲染模板生成最终字符串
    html = template.render(username="Jinja用户")
    # 输出渲染后的 HTML 字符串
    print(html)
  • 传递对象、列表等复杂数据

    • Jinja2 会自动支持字典、列表、Python 对象等,模板中可以用点(.)或方括号([])访问属性。
    • 支持循环、判断、过滤器(|)等功能。

总结:

  • Jinja2 模板渲染即“模板 + 数据 = HTML字符串”
  • 模板语法自然,变量用 {{ }},代码逻辑用 {% %}

2.1 Python 代码 #

# 导入Jinja2的Template、Environment与FileSystemLoader
from jinja2 import Template, Environment, FileSystemLoader

# 方式1:直接用字符串创建模板对象
template = Template('Hello {{ name }}!')
# 用 render 方法渲染模板,传入变量name
result = template.render(name='World')
# 输出渲染结果
print(result)  # Hello World!

# 方式2:从文件夹加载模板
env = Environment(loader=FileSystemLoader('templates'))
# 获取名为'my_template.html'的模板文件
template = env.get_template('my_template.html')
# 渲染模板,传递title和users变量
result = template.render(title='首页', users=['Alice', 'Bob'])

2.2 模板文件 my_template.html #

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>用户列表</h1>
    <ul>
    {% for user in users %}
        <li class="{{ loop.cycle('odd', 'even') }}">
            {{ user }}
            {% if user == 'Alice' %} (管理员){% endif %}
        </li>
    {% endfor %}
    </ul>

    <p>用户数量: {{ users|length }}</p>
</body>
</html>

3. 高级功能 #

3.1 自定义过滤器 #

自定义过滤器可以让你在模板表达式中对变量进行特殊处理。例如常见的自定义时间格式化:

  1. 定义过滤器函数:接收输入值和参数,返回处理结果。
  2. 注册到Jinja2环境:将函数与过滤器名称绑定。

示例:

# 定义一个将datetime对象格式化为指定字符串的过滤器
def datetime_format(value, format='%Y-%m-%d %H:%M'):
    return value.strftime(format)
# 方式2:从文件夹加载模板
env = Environment(loader=FileSystemLoader('templates'))
# 注册到模板环境,命名为datetime_format
env.filters['datetime_format'] = datetime_format
# 获取名为'my_template.html'的模板文件
template = env.get_template('my_template.html')
# 渲染模板,传递title和users变量
result = template.render(title='首页', users=['Alice', 'Bob'],now=datetime.now())
print(result)

模板调用方法:

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>用户列表</h1>
    <ul>
    {% for user in users %}
        <li class="{{ loop.cycle('odd', 'even') }}">
            {{ user }}
            {% if user == 'Alice' %} (管理员){% endif %}
        </li>
    {% endfor %}
    </ul>

    <p>用户数量: {{ users|length }}</p>
    <p>当前时间: {{ now|datetime_format('%Y-%m-%d') }}</p>
</body>
</html>

常见用途:

  • 格式化日期/时间
  • 字符串大小写转换
  • 金额格式化
  • 过滤敏感内容等

自定义过滤器让模板输出更灵活丰富。

3.2 宏(类似于函数) #

宏(macro)类似于编程语言中的函数,可以将模板中经常复用的片段(如表单控件、按钮等)进行抽象,简化页面结构,方便维护和重用。

主要特点:

  • 用{% macro 宏名(参数) %}...{% endmacro %}定义。
  • 可带参数,可有默认值。
  • 在模板中可多次调用,减少重复代码。
  • 支持条件判断、循环等模板语句。

示例说明:

下面示例中,定义了一个 input 宏,可用于渲染不同类型的表单输入控件。通过传递不同参数,宏可以灵活生成各种输入框:

# 导入Jinja2模块中的Template、Environment和FileSystemLoader类
from jinja2 import Template, Environment, FileSystemLoader
# 导入datetime模块中的datetime类
from datetime import datetime
# 通过字符串创建一个Jinja2模板对象
template = Template(
    """
    {% macro input(name, value='', type='text') %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
    {% endmacro %}

    {{ input('username') }}
    {{ input('password', type='password') }}
    """
)
# 渲染模板,无需传递变量
result = template.render()
# 打印渲染结果
print(result)  # Hello World!

宏可在页面任意位置调用,并根据传参输出不同内容,非常适合构建复杂的表单、表格、按钮组等 UI 片段。

常见应用:

  • 表单控件生成
  • 按钮组件
  • 表格行/列渲染
  • 可复用的布局片段

3.3 包含模板 #

包含模板(include)用于将其他模板的内容插入当前模板,方便页面结构复用、模块化开发。

主要用法:

  • 用 {% include '文件名' %} 语句引入外部模板片段
  • 通常用于页头、页脚、导航栏等公共部分的抽取
  • 被包含的模板可以是完整页面,也可以是 HTML 片段

特点:

  • 当前模板的变量会传递给被包含的模板,可以直接使用
  • 支持在任何地方包含,可嵌套使用

简单案例:

例如,有三个模板文件:

  • header.html:头部导航
  • footer.html:底部版权
  • main.html:主题内容

在主页面模板中:

{% include 'header.html' %}
主体内容
{% include 'footer.html' %}

最终渲染结果会自动拼接 header、主体、footer,为页面开发带来极大便利。

3.4 空白控制 #

空白控制(Whitespace Control)用于精细调整 Jinja2 模板渲染时生成的 HTML 代码中的空行和缩进,减少不必要的空白,输出更为简洁。

主要用法:

  • 在 Jinja2 语法标签(如 {% ... %} 或 {{ ... }})的开始或结束处添加减号(-),去除标签前或后的空白符。
    • {%- ... %}:去除标签前的空白
    • {% ... -%}:去除标签后的空白
    • 两侧一起用:{%- ... -%},去除前后空白
  • 适用于 for、if、block、include 等所有 Jinja2 块

案例说明: 原始模板如下,未做空白控制:

<ul>
{% for user in users %}
    <li>{{ user }}</li>
{% endfor %}
</ul>

渲染结果中每个<li>之间都会有换行和缩进。

如做空白控制:

<ul>
{%- for user in users %}
    <li>{{ user }}</li>
{%- endfor %}
</ul>

渲染结果会去除多余的空行,使列表紧凑。

更多示例:

  1. 控制 if 块渲染的空白:

    {% if active -%}
    <p>激活状态!</p>
    {%- endif %}
  2. 同时去除变量标签两端的空白:

    {{- name -}}

    这样name变量前后的所有空格都会被去除。

小结:

  • 推荐对循环、条件语句、include 等适度加减号,保持输出页面整洁
  • 复杂模板建议配合编辑器显示空白字符,方便调试
{% for item in items -%}    {# 减号去除空白 #}
    {{ item }}
{%- endfor %}

4. 安全特性 #

Jinja2 模板引擎内置多种安全机制,有助于防止常见的 Web 安全问题,主要包括:

1. 自动转义(Autoescape) #

  • 默认自动转义 HTML 特殊字符(如 <, >, & 等),有效防止 XSS(跨站脚本攻击)。
  • 仅当渲染为 HTML/XML 输出时自动启用,对纯文本或自定义类型需手动开启。

2. |safe 过滤器 #

  • 某些情况下输出已经明确安全的 HTML,可用 |safe 过滤器防止其被再次转义。
  • 使用时需 确保内容可信,否则容易引入安全隐患。

3. 手动转义与强制转义 #

  • |escape 或简写 |e 过滤器,可强制对变量进行 HTML 转义。
  • 支持嵌套:可以多次转义内容。

4. 禁用代码执行 #

  • Jinja2 仅限模板语法,不允许模板中直接执行任意 Python 代码(如 os.system),隔离了危险操作。

5. 配置和过滤器加固 #

  • 建议只将可信数据传入模板。
  • 可自定义过滤器对特定内容进行二次过滤,增强安全性。

注意事项:

  • 自动转义只对变量起效。模板中的静态 HTML、JS 需开发者自行防护。
  • 动态生成的 JS、CSS、属性等内容,建议配合转义函数或模板过滤器。

举例说明:

{{ user_input }}       {# 自动转义,防XSS #}
{{ user_input|safe }}  {# 明确信任,取消转义,注意风险 #}
{{ user_input|escape }}{# 手动强制转义 #}

通过合理利用 Jinja2 的安全特性,可以大大降低模板渲染带来的安全风险,保障 Web 应用安全。

5. 常见应用场景 #

  1. Web 开发:Flask、Django 模板
  2. 配置管理:Ansible、SaltStack 的模板文件
  3. 文档生成:API 文档、报告生成
  4. 邮件模板:动态邮件内容
  5. 代码生成:根据模板生成代码文件

6. 最佳实践 #

  1. 逻辑与表现分离:模板中尽量少做复杂计算
  2. 使用模板继承:保持布局一致性
  3. 合理使用宏:复用 UI 组件
  4. 配置自动转义:确保安全
  5. 缓存模板:生产环境中提升性能
← 上一节 jieba 下一节 langchain →

访问验证

请输入访问令牌

Token不正确,请重新输入