Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic table with Python

I am developing a small site, which must fetch some data from an API and display it in a table (I don't know how much rows I will need, it depends on the API). I selected Python as backend programming language and Flask as a web-framework. I need to make a request to API from Python on page start and display it's result in a table in HTML template. render_template with some parameters can't do that - because it can't dynamically display HTML elements, just text. How can I do it without JS/JQuery or using it minimally? This is my table code (it's Bootstrap 4)

<table class="table table-bordered" id="users">
  <thead>
    <tr>
      <th>ID</th>
      <th>Имя</th>
      <th>Фамилия</th>
      <th>Действие</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td rowspan="1">3319</td>
      <td>...</td>
      <td>...</td>
      <td><a href="#">Выбрать</a></td>
  </tbody>
</table>
like image 333
crinny Avatar asked Aug 25 '18 17:08

crinny


3 Answers

I've edited @juegern's answer to work with <a> tags and now my code looks so:

<table class="table table-striped" id="users">
 <thead>
  {%- for column in columns %}
     <th>{{ column }}</th>
  {%- endfor %}
 </thead>

 <tbody>
 {%- for row in items %}
    <tr>
    {%- for column in columns %}
        {% if row[column]['link'] %}
            <td><a href="{{ row[column]['link'] }}">{{ row[column]['text'] }}</a></td>
        {% else %}
            <td>{{ row[column] }}</td>
        {% endif %}
    {%- endfor %}
    </tr>
 {%- endfor %}
 </tbody>
 </table>

Code to apply some data to this table from Flask: items_list = [{'1': 'Hello', '2': 'World', '3': {'link': '#', 'text': 'Open'}}, {'1': 'World', '2': 'Hello', '3': {'link': '#', 'text': 'Open'}}] return render_template('your_file_name.html', columns=['1', '2', '3'], items=items_list)

like image 163
crinny Avatar answered Nov 16 '22 04:11

crinny


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/

like image 39
Juergen Avatar answered Nov 16 '22 06:11

Juergen


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!

like image 10
Attack68 Avatar answered Nov 16 '22 05:11

Attack68