Search code examples
pythonflaskjinja2

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


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?


Solution

  • 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.