Dynamic table with Python

When using Jinja2, you can dynamically create your table using the scripting possibilities of Jinja2, with a syntax rather similar to Python:

<table>
 <thead>
  {%- for column in columns %}
     <th>{{ column }}</th>
  {%- endfor %}
 </thead>

 <tbody>
 {%- for row in items %}
    <tr>
    {%- for column in columns %}
       <td>{{ row|attr(column) }}</td>
    {%- endfor %}
    </tr>
 {%- endfor %}
 </tbody>
 </table>

At the call of render_template, you need to provide two variables "columns" containing a list of columns of the rows and "items" containing the rows.

No need to use JS.

If you want to support some special data types, like links, you can do so by using if statements in the template.

See the reference of Jinja2 for more details: http://jinja.pocoo.org/docs/2.10/templates/


You might also be interested in this pattern, using python package pandas:

import pandas as pd

@app.route('/table')
def display_table():
    # do something to create a pandas datatable
    df = pd.DataFrame(data=[[1,2],[3,4]])
    df_html = df.to_html()  # use pandas method to auto generate html
    return render_template('page.html', table_html=df_html)

then inside the page.html include the following:

{{ table_html | safe }}

you need to include the safe filter so that it renders raw html without escaping any of the characters.

This will render the following, which you can also stylise with the arguments and the Styler available in pandas.

<table border="1" class="dataframe">  
<thead>    
<tr style="text-align: right;">      
<th></th>    
<th>0</th>      
<th>1</th>    
</tr>  
</thead>  
<tbody>    
<tr>      
<th>0</th>     
<td>1</td>     
<td>2</td>   
</tr>    
<tr>      
<th>1</th>    
<td>3</td>     
<td>4</td>    
</tr> 
</tbody>
</table>

EDIT: FYI this is also convenient for problems where you have complicated, or dynamic conditional formatting, that is easier to style on the python/pandas server side, and not have to worry about the html template. Of course it depends what you are doing but I argue this is more maintainable in some situations - like mine!