Search code examples
pythonflaskjinja2

Nested jinja loops not updating inner loop references


I have a database with items and categories for those items, listed by category. My code is only comparing the first category and not updating within the inner loop.

 {% for category in categories %}
    <h1>{{category}}</h1>
    {% for item in items %}
        {% if item.category == category %}
            <p>{{item.name}} {{item.category}}</p>
            <tr>
                <td><p>{{item.name}}</p></td>
                <td><p>{{item.category}}</p></td>
                <td>
                    <form action="/delete_item" method="post">
                        <input name="id" type="hidden" value="{{item.id}}">
                        <input type="submit" value="Delete" class="btn btn-danger">
                     </form>
                </td>
            </tr>
        {% endif %}
    {% endfor %}
{% endfor %}

When the code runs it outputs every category and it outputs all items that are associated with the first category only. It seems to not be updating "category" in line 4. So the loop is running but the inner loop is never seeing that the category has been updated in the outer loop. Categories is passed as a completely separate parameter than items. If I hard-code another category it will output only those items in that category.

I'm trying to get a categorized list with a heading tag for each category and then the items in that category. It's only doing it for the first category, even though it's running through each category in the outer loop.


Solution

  • Your code example gives exactly the expected result. So it seems like your problem is elsewhere.

    Another option is to filter the items based on the category attribute using the selectattr filter. This filters a sequence of objects by applying a test to the specified attribute of each object and selecting only those objects that pass the test.

    {% set items = items | list -%} {# convert a generator to a list #}
    {% for category in categories -%}
        <h1>{{category}}</h1>
        {% for item in items|selectattr('category', 'equalto', category) -%}
            <p>{{ item.name }} {{ item.category }}</p>
        {% endfor -%}
    {% endfor -%}
    

    If you want to ignore empty categories, take a look at groupby.


    I think you don't have a list of items, but a generator that you can only iterate over once. For this reason the additional line to convert to a list.

    {% set items = items | list -%}