首页 > 解决方案 > jinja2.exceptions.TemplateSyntaxError:遇到未知标签'do'

问题描述

我对 Jinja 不是很熟悉,并且在我的模板中使用“do”语句时遇到了一些问题。我正在阅读其他帖子,并试图修复它,但仍然没有运气。

这是我如何尝试调用它的部分输出。

注意:我的解释器说没有使用“扩展”:

import jinja2
import csv
from jinja2.ext import Extension


jinja_env = jinja2.Environment(extensions=['jinja2.ext.do'])

with open ('mycsv.csv') as f:
    read_csv = csv.DictReader(f)
    for line in read_csv:
        with open ( line["name"] +"_config.txt", 'w') as output:                    
            with open(r"My_Template.j2") as t:
                my_templ = t.read()

            temmplate = jinja2.Template(my_templ)
            output.write(temmplate.render(line))

这只是我想如何使用“do”的示例,而不是确切的模板(即单独的文件)

{%- for Z in range (1,X+1) %}
{%- do  Y-=1 %}
something {{Z}} something_else {{Y}}
{%- endfor %}

错误:

jinja2.exceptions.TemplateSyntaxError: Encountered unknown tag 'do'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.

===== 更新 ======

再次感谢!如果我在 Jinja 中定义我的变量,那效果很好。但是,如果我使用来自 csv 的变量,我会遇到一些问题。我希望输出如下:

increment 1 decrement 14
increment 2 decrement 13

所以这很好用。

{% set one = 1 %}
{% set fourteen = 14 %}
{% set base = 3 %}
{% for inc in range(base) %}
switch {{one+base}} priority {{fourteen - base}}
{% endfor %}

但是,如果我尝试使用 csv 中的变量,则所有内容都被视为字符串。如果我删除:

{% set base = 3 %}

我得到:

TypeError: "str" object cannot be interpreted as an integer.

所以我尝试用以下方法修改神社:

{% set base = int(base) %}

{% set base = integer(base) %}

我分别得到以下两个错误:

jinja2.exceptions.UndefinedError: "int" is undefined
jinja2.exceptions.UndefinedError: "integer" is undefined

如果我在 python 中更改它,它会显示“未定义”:

base = int(line["base"])
print(base)
print(type(base))

Output:
3
<class 'int'>

  File "<template>", line 6, in top-level template code
TypeError: 'Undefined' object cannot be interpreted as an integer

这是第 6 行:

{% for inc in range(base) %}

有没有办法在 Jinja 模板中判断一个值是整数类型?

标签: python-3.xjinja2

解决方案


您的问题是,当您在环境中启用do扩展时jinja_env,您并没有使用环境来获取模板。jinja_env.get_template如果您希望环境设置相关,则需要使用该方法加载模板。

例如,假设模板在当前目录中可用,我们可以像这样重写您的代码:

import jinja2
import csv
from jinja2.ext import Extension


jinja_env = jinja2.Environment(
    loader=jinja2.FileSystemLoader('.'),
    extensions=['jinja2.ext.do']
)

with open ('mycsv.csv') as f:
    read_csv = csv.DictReader(f)
    for line in read_csv:
        with open("{name}_config.txt".format(**line), 'w') as output:
            template = jinja_env.get_template('My_Template.j2')
            output.write(template.render(line))

您将遇到第二个问题,即您do在示例中使用的语句无效。你不能写...

{% do Y -= 1 %}

...因为那不是一种表达方式。您可以将“表达式”解释为“可以放在赋值语句右侧的东西”。所以这些是有效使用的例子do

{% do somevar.append('a value') %}
{% do somedict.setdefault('name', 'alice') %}

对于变量赋值,Jinja 有{% set ... %}表达式。您可以使用它来减少变量。例如,这有效:

{% set x = 5 %}
{% set x = x - 1 %}

不幸的是, set 并没有像创建一个新变量那样 修改变量,这意味着这在循环中不起作用,因为新变量的范围仅限于当前循环迭代。也就是说,如果我们要写:for

{% set x = 5 %}
{% for y in range(5) %}
{% set x = x - 1 %}
{{ x }}
{% endfor %}

输出将是:

4
4
4
4
4

但是,我们可以通过编写来获得我们正在寻找的行为:

{% set x = 5 %}
{% for y in range(5) %}
{{ x-y }}
{% endfor %}

这将产生:

5
4
3
2
1

推荐阅读