4

I'm trying to convert some old Smarty templates to Jinja2.

Smarty uses an eval statement in the templates to render a templated string from the current context.

Is there an eval equivalent in Jinja2 ? Or what is a good workaround for this case ?

Julien Tanay
  • 1,214
  • 2
  • 14
  • 20

4 Answers4

1

Use the @jinja2.contextfilter decorator to make a Custom Filter for rendering variables:

from flask import render_template_string
from jinja2 import contextfilter
from markupsafe import Markup


@contextfilter
def dangerous_render(context, value):
    Markup(render_template_string(value, **context)).format()

Then in your template.html file:

{{ myvar|dangerous_render }}
Alan Hamlett
  • 3,160
  • 1
  • 23
  • 23
0

I was looking for a similar eval use case and bumped into a different stack overflow post.

This worked for me

routes.py

def index():
    html = "<b>actual eval string</b>"
    return render_template('index.html', html_str = html)

index.html

<html>
    <head>
        <title>eval jinja</title>
    </head>
    <body>
        {{ html_str | safe }}
    </body>
</html>

Reference : Passing HTML to template using Flask/Jinja2

Naveen Vijay
  • 15,928
  • 7
  • 71
  • 92
0

If you are using jinja version 3.0, contextfilter has deprecated and removed in Jinja 3.1. Use pass_context() instead. Refer here for more details pertaining this.

from jinja2 import pass_context, Template
from markupsafe import Markup


@pass_context
def foo(context, value):
    return Markup(Template(value).render(context)).render()

then in your template

 {{ myvar|foo }}
0

Based on the answers from Alan Hamlett and Hilario Nengare, I implemented the following "eval" filter for Jinja2 (>=3.0). I found that the case of undefined input should also be handled, plus I added the ability to specify additional variables as input for the expression:

import jinja2

@jinja2.pass_context
def filter_eval(context, input, **vars):
    if input == jinja2.Undefined:
        return input
    return jinja2.Template(input).render(context, **vars)

Usage, when adding filter_eval() as filter "eval":

  • Template source:

    {% set rack_str = 'Rack {{ rack }}' %}
    {{ rack_str | eval(rack='A') }}
    
  • Rendered template:

    Rack A
    
Andreas Maier
  • 2,724
  • 1
  • 26
  • 30