mot*_*oth 2 python jinja2 flask
我试图从Jinja2模板中获取所有未定义的变量。假设我有如下模板。
tmpstr = """
{% for row in csv %}
sample {{row.field1}} stuff {{row.field2}} morestuff {{row.field3}}
{% endfor %}
"""
Run Code Online (Sandbox Code Playgroud)
然后输入字典如下
cxt = {'csv': [
{'field3': 1234, 'field4': 12314},
{'field3': 2222, 'field4': 1213}
]}
Run Code Online (Sandbox Code Playgroud)
这是我尝试渲染它的方式。
env = Environment(undefined=Undefined)
tmp = env.from_string(tmpstr)
tmpsrc = tmp.render(cxt)
print(tmpsrc)
Run Code Online (Sandbox Code Playgroud)
模板期望变量field1
,field2
并field3
存在。但是field1
,field2
并且不存在。我的目的是找到所有缺失的变量。
Jinja2默默地忽略丢失的变量。因此,我尝试添加StrictUndefined
选项:
errs = []
try:
env = Environment(undefined=StrictUndefined)
tmp = env.from_string(tmpstr)
tmpsrc = tmp.render(cxt)
except Exception as e:
errs.append(str(e))
print(errs)
Run Code Online (Sandbox Code Playgroud)
但是这次jinja2 只抱怨第一个缺少的变量是field1
。
因此,我尝试了另一种选择DebugUndefined
。该选项不会引发异常,并且不会丢失模板输出中缺少的变量占位符。因此,我无法收集丢失的变量。
您能建议我如何在jinja2模板中丢失变量吗?
如果有人想尝试一下,这是可运行的代码:
from jinja2 import BaseLoader,Environment,StrictUndefined,DebugUndefined,Undefined
tmpstr = """
{% for row in csv %}
sample {{row.field1}} stuff {{row.field2}} morestuff {{row.field3}}
{% endfor %}
"""
cxt = {'csv': [
{'field3': 1234, 'field4': 12314},
{'field3': 2222, 'field4': 1213}
]}
env = Environment(undefined=Undefined)
tmp = env.from_string(tmpstr)
tmpsrc = tmp.render(cxt)
print('CASE 1: undefined=Undefined')
print(tmpsrc)
errs = []
try:
env = Environment(undefined=StrictUndefined)
tmp = env.from_string(tmpstr)
tmpsrc = tmp.render(cxt)
except Exception as e:
errs.append(str(e))
print('CASE 2: undefined=StrictUndefined')
print(errs)
errs = []
try:
env = Environment(undefined=DebugUndefined)
tmp = env.from_string(tmpstr)
tmpsrc = tmp.render(cxt)
except Exception as e:
errs.append(str(e))
print('CASE 3: undefined=DebugUndefined')
print(errs)
print(tmpsrc)
Run Code Online (Sandbox Code Playgroud)
我使用找到了解决您问题的方法 jinja2.make_logging_undefined
。我和你在同一条船上,一直在寻找答案。大多数答案都指向我使用已解析的模板,但是我无法弄清楚如何将上下文放入已解析的模板中。
我终于可以使用进行这项工作make_logging_undefined
。如果要查找所有未定义的变量,请确保仅使用Undefined
基类而不是StrictUndefined
。使用StrictUndefined
将导致Jinja在未定义的第一次遇到时引发异常。
只是免责声明:我不是python也不是jinja专家,因此代码不是最有效或结构化的代码。但这符合我的目的。这只是POC代码。
这是代码:
import jinja2
import logging
from jinja2 import Environment, Undefined
from jinja2.exceptions import UndefinedError
def main():
templateLoader = jinja2.FileSystemLoader( searchpath="D:\\somelocation\\" )
logging.basicConfig()
logger = logging.getLogger('logger')
LoggingUndefined = jinja2.make_logging_undefined(logger=logger,base=jinja2.Undefined)
templateEnv = jinja2.Environment( loader=templateLoader, undefined=LoggingUndefined)
TEMPLATE_FILE = "./example1.jinja"
template = templateEnv.get_template( TEMPLATE_FILE )
FAVORITES = [ "chocolates", "lunar eclipses", "rabbits" ]
# Specify any input variables to the template as a dictionary.
templateVars = { "title" : "Test Example",
"description" : "A simple inquiry of function.",
"favorites" : FAVORITES,
"whatever" : "1"
}
# Finally, process the template to produce our final text.
try:
outputText = template.render( templateVars )
except ( UndefinedError) as err:
print err
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
example1.jinja:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{{ title }}</title>
<meta name="description" content="{{ description }}" />
</head>
<body>
<div id="content">
<p>Greetings visitor! These are a list of my favorite things:</p>
<ul>
{% for item in favorites %}
<li>{{ item }}</li>
<li>My favorites: {{ favorites[1] }} </li>
{% endfor %}
{{ undefined_var1 }}
{{ underfined_var2 }}
</ul>
</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
这是示例输出:
WARNING:logger:Template variable warning: undefined_var1 is undefined
WARNING:logger:Template variable warning: underfined_var2 is undefined
Run Code Online (Sandbox Code Playgroud)
使用find_undeclared_variables
withDebugUndefined
你可以正确地引发一个异常,提到所有丢失的变量:
import jinja2
from jinja2.meta import find_undeclared_variables
env = jinja2.Environment(undefined=jinja2.DebugUndefined)
template = env.from_string('foo={{ foo }}, bar={{ bar}}, baz={{ baz }}')
# Render template without passing all variables
rendered = template.render(foo=1)
# Check if rendering was done correctly
ast = env.parse(rendered)
undefined = find_undeclared_variables(ast) # {'bar', 'baz'}
if undefined:
raise jinja2.UndefinedError(f'The following variables are undefined: {undefined!r}')
Run Code Online (Sandbox Code Playgroud)
如果您更喜欢日志记录,您可以使用undefined
.
PS:我对 Jinja 比较陌生,但我很惊讶这不是env.render
. 我想知道为什么作者/维护者认为默认情况下忽略丢失的变量是一件好事......
归档时间: |
|
查看次数: |
2396 次 |
最近记录: |