How to structure data to easily build HTML tables in Flask
Asked Answered
S

3

15

I am trying to create HTML tables from data stored in a table. My data is read from a table and converted into a dict of lists, e.g.:

x = {'date':[u'2012-06-28', u'2012-06-29', u'2012-06-30'], 'users': [405, 368, 119]}

My goal is to create an HTML table with the following structure for an arbitrary list length:

<table>
  <thead>
    <th>Date</th>
    <th>Users</th>
  </thead>

  <tbody>      
    <tr>
      <td>2012-06-28</td>
      <td>405</td>
    </tr>
    <tr>
      <td>2012-06-29</td>
      <td>368</td>
    </tr>
    <tr>
      <td>2012-06-30</td>
      <td>119</td>
    </tr>
  </tbody>
</table> 

I have tried doing this two incorrect ways in my Flask template:

<tbody>
  {% for line in x %}
    <tr>
      <td>{{ x.date|tojson|safe }}</td>
      <td>{{ x.users }}</td>
     </tr>
   {% endfor %}
</tbody>

Which prints the entire list into each column.

And:

{% for date in x.date %}
  <tr><td>{{ date|tojson|safe }}</td></tr>
{% endfor %}

{% for users in x.users %}
  <tr><td>{{ users }}</td></tr>
{% endfor %}

Which simply prints everything into the first column.

These experiments and many other dead ends lead me to believe that there is no simple way to build the table as I would like given my current data structure.

Given this, I have two questions:
1) How would I go about building the table using my current data structure?
2) What is the standard or ideal way to structure data for this use case?

Thanks in advance.

Sillimanite answered 9/11, 2012 at 20:55 Comment(0)
Z
32

Like you said, you could either change your data structure, or change your template code. Here is one way to keep the current structure:

{% for row_index in range(x['date']|count) %}
    <tr>
      <td>{{ x[row_index]['date']|tojson|safe }}</td>
      <td>{{ x[row_index]['users'] }}</td>
    </tr>
{% endfor %}

Or you could restructure your data in python:

x = zip(x['date'], x['users'])

And then use this template:

{% for row in x %}
    <tr>
      <td>{{ row[0]|tojson|safe }}</td>
      <td>{{ row[1] }}</td>
    </tr>
{% endfor %}

You can also structure the data so that the template does not depend on the order of the cells:

from itertools import izip
x = [dict(date=d, user=u) for d, u in izip(x['date'], x['users'])]

Then you can access your data like this:

{% for row in x %}
    <tr>
      <td>{{ row['date']|tojson|safe }}</td>
      <td>{{ row['user'] }}</td>
    </tr>
{% endfor %}
Zingg answered 9/11, 2012 at 21:0 Comment(2)
This is great, thank you. Before I accept, can you point me to some documentation for those pipe commands? Didn't realize there were more of them.Sillimanite
Yep. Flask uses Jinja2 for its templates, so you can use anything from jinja.pocoo.org/docs/templates/#builtin-filters.Zingg
T
5

You might use Flask-Table or for something more complex even leverage Flask-Admin.

Tangy answered 26/9, 2014 at 0:41 Comment(0)
K
2

Yeah, you really want to use a list of dictionaries instead of a dictionary of lists, that works out better with Jinja2

Knopp answered 9/11, 2012 at 21:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.