'After rendering a Jinja2 template, can I get the set values?
I want to render a Jinja2 template, and after the rendering, read the values that were set by it:
import jinja2
template = jinja2.Template("""
{% set number = 42 %}
Hello {{name}} {{number}}!
""")
vars = {"name": "Ned"}
print(template.render(vars).strip())
print(vars)
This prints:
Hello Ned 42!
{'name': 'Ned'}
Is there something I can do after template.render that would give me the value of number? Also, I need to do it without knowing the name number beforehand. I want to discover whatever values have been set in the template.
Solution 1:[1]
Here's a way to do it without using functions that are documented, but say not to use them:
import jinja2
template = jinja2.Template("""
{% set number = 52 %}
{% set choice = "apple" %}
Hello {{name}} {{number}}!
{% if number > 50 %}
More than 40!
{% set also = 'foo' %}
{% endif %}
""")
ctx = template.new_context(vars = {"name": "Ned"})
template.render(ctx)
mod = template.module
template_vars = {n:getattr(mod, n) for n in dir(mod) if not n.startswith("_")}
print(template_vars)
This prints:
{'also': 'foo', 'choice': 'apple', 'number': 52}
Solution 2:[2]
With the context provided:
import jinja2
import re
template = jinja2.Template("""
{% set number = 42 %}
Hello {{name}} {{number}}!
""")
vars = {"name": "Ned"}
rendered = template.render(vars).strip()
print(vars)
print(rendered)
changed_var_value = re.findall(r'Hello[\s\S]*\s{1}(.*)!', rendered)
print(f'var after the greeting: {changed_var_value}')
output:
{'name': 'Ned'}
Hello Ned 42!
var after the greeting: ['42']
Solution 3:[3]
I guess, this is a kinda hack but it seems you can do something with Context from jinja2.runtime like
$ cat show_vars.py
import jinja2
template = jinja2.Template("""
{% set number = 42 %}
Hello {{name}} {{number}}!
""")
vars = {"name": "Ned"}
print(template.render(vars).strip())
print(vars)
from jinja2 import Environment
from jinja2.runtime import Context
env = Environment()
ctx = Context(env, vars, '', template.blocks)
list(template.root_render_func(ctx))
print(ctx.vars)
print(ctx.get_all())
$ python show_vars.py
Hello Ned 42!
{'name': 'Ned'}
{'number': 42}
{'name': 'Ned', 'number': 42}
As @nedbat pointed out, one can also achieve the same with
import jinja2
template = jinja2.Template("""
{% set number = 42 %}
Hello {{name}} {{number}}!
{% if number > 50 %}
More than 40!
{% set also = 'foo' %}
{% endif %}
""")
ctx = template.new_context(vars = {"name": "Ned"})
list(template.root_render_func(ctx))
print("get_all:", ctx.get_all())
print("exported_vars:", ctx.exported_vars)
print("vars:", ctx.vars)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ned Batchelder |
| Solution 2 | jeroenflvr |
| Solution 3 |
