How to do nested loops and if statements in Flask/Jinja; create inventory table

Issue

I’m trying to make an inventory table for showing a card’s id/name. I got it working in python but I don’t know how to convert it to jinja to show on the webpage.

I want to get the items in a user’s inventory and display 4 in a row then go down a column repeating and if there’s less than 4, display however many left.

I recreated it in a helper python file(addcards.py) to see if I could get it to work without having to deal with refreshing the webpage

app.py


def print_table():

    user_inventory = db.execute("SELECT * FROM inventory WHERE user_id = 1")  # gets users inventory
    items = len(user_inventory)  # gets how many items in inventory
    columns = 4  # random number of columns wanted in table
    rows = math.ceil(items / columns)  # number of rows need to fit items 
    default_col = columns  # var for columns that wont change
    i = 0  # counter var
    
    for row in range(rows):  # makes the number of rows
        for col in range(columns):  # makes number of columns to print
            card_db = db.execute("SELECT * FROM cards WHERE id = ?", 
                                 user_inventory[i]["card_id"])  # gets card info from db going through users inventory
            print("[" ,card_db[0]["card_name"], "]" , end="")  # print the unique id/name of card depending on key
            i += 1  # moves counter over to next item in inventory
        columns =  items - columns  # calc to see how many items left to display
        if columns >= default_col:  # check if items over number of columns wanted 
            items = columns  # sets items leftover
            columns = default_col # sets column back to columns wanted for next row
        print()  # end row
    return

addcards.py

@app.route("/inventory", methods=["GET"])

@login_required

def inventory():

    user_id = session["user_id"]
    user = db.execute("SELECT * FROM users WHERE id = ?", user_id)  # Search db for users info
    username = user[0]["username"]  # Get username from 1st row key="username"
    
    return render_template("inventory.html", username=username)

inventory.html

{% extends "layout.html" %}

{% block title %}
    Inventory
{% endblock %}

{% block main %}
    <h1>Inventory</h1>

{% endblock %}

endgoal for id table

end goal for name table

Solution

I suggest you do something like this. Same result, just simpler code to make into jinja (assuming thats what you want, I will edit or delete this if you clarify something different in the comments)

I changed the structure so that the python passes a list of cards to jinja. Then in jinja, it loops through the cards, adding a new line every time the loop index is a multiple of the number of columns that were set.

Python:

columns = 4

cards = []
user_inventory = db.execute("SELECT * FROM inventory WHERE user_id = 1")
for id in user_inventory:
    card_db = db.execute("SELECT * FROM cards WHERE id = ?", id["card_id"])
    cards.append(card_db[0]["card_name"])

return render_template("inventory.html", cols = columns, cards = cards)

Jinja (inventory.html):

{% extends "layout.html" %}

{% block title %} Inventory {% endblock %}

{% block main %}
<h1>Inventory</h1>

<span class="inventory">
    {%for c in cards%}
        [{{c}}]
        {%if loop.index%cols == 0%}
            <br>
        {%endif%}
    {%endfor%}
</span>
{% endblock %}

The above will show exactly what your images show only on a webpage.

If you want to get fancy, you can do something similar only with a table. The nice thing about the way this is set up is that we dont need to change the python, only the jinja.

{% block main %}
<h1>Inventory</h1>

<table>
    <tr>
        {%for c in cards%}
            <td>{{c}}</td>
            {%if loop.index%cols == 0%}
                </tr>
            {%endif%}
        {%endfor%}
    </tr>
</table>

<!-- Borders just for demonstration-->
<style>
    td {
        border: 1px solid black;
    }
</style>
{% endblock %}

Answered By – Finn E

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published