RocketSocks22
RocketSocks22

Reputation: 411

Nested Dictionary to Jinja Table w/ Flask

I'm very new to web dev/Flask/HTML so apologies in advance if my problem is not laid out clearly. I have a nested dictionary with the following structure:

dict = {"12-30-2019": 
             {"Meat": 
                     "Calories": 800,
                     "Protein": 20,
                     "Fat": 10
             },
             {"Potato": 
                     "Calories": 200,
                     "Protein": 15,
                     "Fat": 12
             }
       }

dict={'12-30-2019': {'meat': {'Calories' : 800, 'Protein': 20, 'Fat': 10}, 'Potato': {'Calories': 200, 'Protein': 15, 'Fat': 12}}} 

I'm struggling to design the template somewhat like this:

       |            Date          |
       ----------------------------
       | Calories | Protein | Fat |
-----------------------------------
Meat   |   800    |    20   |  10 | 
-----------------------------------
Potato |   200    |    15   |  12 |

My failed attempt so far is this:

    <table>
        {% for parent_key, parent_value in mfp_data.items() %}
        <th> {{ parent_key }}</th>
        <tr>
            {% for child_key, child_value in parent_value.items() %}
                <th> {{ child_key }} </th>
                {% for baby_key, baby_value in child_value.items() %}
                <th> {{ baby_key }} </th>
                <td> {{ baby_value }}</td>
                {% endfor %}
            {% endfor %}
        </tr>
        {% endfor %}
    </table>

Any suggestions on how I may be able to elegantly do this?

Upvotes: 1

Views: 1514

Answers (1)

Rok Povsic
Rok Povsic

Reputation: 4925

Ideally you would, before passing the data to the template/view/HTML part, transform this data from a relatively complex dictionary to a structure which the template can simply read and display. You want to have as little logic as possible in the template part, and only iterate through pre-made lists.

Here's a solution that does that, in part. It extracts the dates and row headers into separate variables so they are easily accessible in the template.

@app.route('/')
def hello_world():
    data = {
        '12-30-2019': {'meat': {'Calories': 800, 'Protein': 20, 'Fat': 10}, 'Potato': {'Calories': 200, 'Protein': 15, 'Fat': 12}},
        '12-31-2019': {'meat': {'Calories': 800, 'Protein': 20, 'Fat': 10}, 'Potato': {'Calories': 200, 'Protein': 15, 'Fat': 12}},
    }

    dates = data.keys()
    row_headers = list(list(data.values())[0].values())[0].keys()

    return render_template("index.html", dates=dates, row_headers=row_headers, mfp_data=data)
<table>
  {% for date in dates %}
    <tr><th colspan="3">{{ date }}</th></tr>
    <tr>
      <th></th>
      {% for row_header in row_headers %}
        <th>{{ row_header }}</th>
      {% endfor %}
    </tr>

    {% for key, values in mfp_data[date].items() %}
      <tr>
        <th>{{ key }}</th>
      {% for value in values.values() %}
        <td>
        {{ value }}
        </td>
      {% endfor %}
      </tr>
    {% endfor %}
  {% endfor %}
</table>

Upvotes: 4

Related Questions