【问题标题】:jinja2: overload how the templates load all variablesjinja2:重载模板如何加载所有变量
【发布时间】:2021-03-17 18:11:27
【问题描述】:

有没有办法重载 jinja 评估所有变量表达式的方式?

我想更改模板系统评估所有变量的方式,在{{ variable }} 表达式和{% if variable %} 类型语句中(我想让它以特定方式从特定位置加载它们,通过名称)。

例如,如果有人将{{ this.is.a.test }} 放入模板中,我想使用 jmespath (https://github.com/jmespath/jmespath.py) 从上下文中的已知字典中加载变量,而不是使用普通路由。它会从这本词典中选择“你好”:

{
  "this": {
    "is": {
      "a": {
        "test": "hello"
      }
    }
  }
}

这也将评估为 true:{% if this.is.a.test == "hello" %}

这是可能的吗?

【问题讨论】:

  • 我不明白这个问题......但听起来你可能想要 jinja2 模板中的 import 指令
  • @JoranBeasley no...更新了问题。希望这会有所帮助

标签: python jinja2


【解决方案1】:

只需将您的 dict 以 context 的形式传入即可。

>>> from jinja2 import Environment
>>> env = Environment()
>>> template = env.from_string('{{ this.is.a.test }}')
>>> context = {
...   "this": {
...     "is": {
...       "a": {
...         "test": "hello"
...       }
...     }
...   }
... }
>>> print(template.render(**context))
hello

有两个因素使这项工作奏效。首先,正如 Jinja 的 documentation 解释的那样:

您还可以使用点 (.) 来访问变量的属性 到标准 Python __getitem__“下标”语法 ([])。

以下几行做同样的事情:

{{ foo.bar }}
{{ foo['bar'] }}

第二个是在传入字典时使用** 将第一级扩展为关键字和值。也就是说,下面两行是完全一样的:

foo(**{'bar': 'baz'})
foo(bar='baz')

当然,Jinja 的Template.render 方法只接受关键字作为根级变量,这样就可以得到你想要的。

【讨论】:

  • 这很酷,但它更多的是对示例的字面解决方案,它不能让我通过 jmespath 运行每个变量名进行评估,这正是我所追求的。我想利用所有的 json 遍历,比如foo.bar[*].name 等。似乎覆盖Environment 上的context_class 可能是一个开始?
  • 我认为您提到 jmespath 只是为了指向一些具有类似功能的库,而不是您必须绝对使用该库。也许你的问题太宽泛了。我建议探索覆盖 context_class 并在遇到困难时提出更集中的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-05
  • 1970-01-01
  • 2018-03-19
  • 2022-07-23
  • 2015-12-08
  • 2015-10-23
  • 1970-01-01
相关资源
最近更新 更多