You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jinja2循环中替代with模板指令的高效实现方案咨询

问题背景

我有一个模板文件letter.txt,内容如下:

Hello {{ first_name }} {{ last_name }}!

(实际场景中变量远不止这两个,此处为简化仅保留first_name和last_name。)

通过以下代码可正常渲染该模板:

from jinja2 import Environment, FileSystemLoader 
environment = Environment(loader=FileSystemLoader("./"))

template = environment.get_template("letter.txt")
template.render(first_name='Jane', last_name='Doe')

现在需要生成包含多组姓名的批量信件,目前的做法是在form_letter.txt模板中使用冗长的with语句引用原letter.txt模板:

{% for person in people %}
    {% with first_name=person.first_name, last_name=person.last_name %}
        {% include 'letter.txt' %}
    {% endwith %}
    ------8<---cut here------------
{% endfor %}

并通过以下代码渲染:

template = environment.get_template("form_letter.txt")
template.render(people=[{'first_name': 'Jane', 'last_name': 'Doe'},
                        {'first_name': 'Bob', 'last_name': 'Builder'},
                        {'first_name': 'Sara', 'last_name': 'Sample'}])

手动编写甚至扩展这种with语句既繁琐又容易出错,想问是否存在更优方式,能从字典类对象的键值对自动在模板内创建命名空间?类似{% with **person %}这样的写法?

解决方案

Jinja2提供了两种简洁的方式,无需手动逐个映射变量:

方式一:使用include的context参数

直接在include时传入context=person,即可将person的键值对注入到letter.txt的上下文,模板内可直接使用对应变量:

{% for person in people %}
    {% include 'letter.txt' with context=person %}
    ------8<---cut here------------
{% endfor %}

无论person是字典还是类对象,Jinja2都会自动识别其键/属性,letter.txt中的{{ first_name }}、{{ last_name }}会直接匹配对应值。

方式二:直接调用模板的render方法

在循环中获取letter.txt模板对象,调用其render方法传入person:

{% for person in people %}
    {{ get_template('letter.txt').render(person) }}
    ------8<---cut here------------
{% endfor %}

默认环境下支持此写法,若有自定义安全限制,需确保模板环境允许调用get_template方法。

内容的提问来源于stack exchange,提问作者mawimawi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 05:27:37