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
相关产品推荐
相关产品推荐

