Flask cannot import enumerate? UndefinedError: 'enumerate' is undefined

Question:

I just write this code in a HTML page.

{% for i, val in enumerate(['a', 'b', 'c']) %}
    <td>
        {{ val }}
    </td>
{% endfor %}

UndefinedError: 'enumerate' is undefined

So, Flask do not support the enumerate?

Asked By: Aleeee

||

Answers:

Flask use Jinja2 to render your template, Jinja2 have a similar python syntax but it’s not python.

What you can do? In your python code:

my_dict = enumerate(some_list)

Then when rendering the template send the dict to it:

render_template('page.html', my_dict=my_dict)
Answered By: Or Duan

As Or Duan says, Jinja2 has its own language. Looks like Python but it’s not Python. So the Python enumerate built-in function is not part of Jinja2 template engine. There are, however, some alternatives you can use:

If you want to enumerate the items in a list you can use the loop.index0 loop special variable:

>>> from jinja2 import Template

>>> t1 = """
... {% for val in ['a', 'b', 'c'] %}
...     <td>
...         {{ loop.index0 }} {{ val }}
...     </td>
... {% endfor %}
... """
>>> Template(t1).render()

Another option is to precalculate the enumerated version of the list:

>>> t2 = """
... {% for i, val in l %}
...     <td>
...         {{ i }} {{ val }}
...     </td>
... {% endfor %}
... """
>>> Template(t2).render(l=enumerate(['a', 'b', 'c']))

And also another one, could be even passing enumerate as a variable too:

>>> t3 = """
... {% for i, val in enumerate(['a', 'b', 'c']) %}
...     <td>
...         {{ i }} {{ val }}
...     </td>
... {% endfor %}
... """
>>> Template(t3).render(enumerate=enumerate)

Flask allows injecting variables automatically into the context of a template by means of Context Processors. So if you want enumerate built-in function to be available for all your templates, this could be a nice solution:

@app.context_processor
def inject_enumerate():
    return dict(enumerate=enumerate)

Thanks to Sean Vieira for this suggestion.

Answered By: dreyescat

I never use Python in templates. I generate the HTML in a controller, put it in a variable, and have the template reference it.

In the controller

@app.route("/xxx")
def xxx():
    html = []
    for (i, val) in enumerate(["a", "b", "c"]):
        html.append(f"""<td> {i} {val}</td>""")
    cells = "n".join(html)
    return render_template("xxx.html", cells=cells)

In the template:

<tr>
{{cells|safe}}
</tr>

Then you have always full python when you do python things, and templates do not get mixed up with Python code.

Answered By: Dirk Roorda
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.