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?
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)
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.
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.
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?
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)
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.
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.