web-dev-qa-db-fra.com

Table dynamique avec Python

Je développe un petit site, qui doit extraire des données d'une API et les afficher dans une table (je ne sais pas combien de lignes il me faudra, cela dépend de l'API). J'ai sélectionné Python comme langage de programmation backend et Flask comme framework web. Je dois faire une demande à l'API de Python au début de la page et afficher le résultat dans un tableau dans un modèle HTML. render_template avec certains paramètres ne peut pas faire cela - parce qu'il ne peut pas afficher dynamiquement des éléments HTML, juste du texte. Comment puis-je le faire sans JS/JQuery ou l'utiliser de manière minimale? Ceci est mon code de table (c'est 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>

4
crinny

Lorsque vous utilisez Jinja2, vous pouvez créer dynamiquement votre table en utilisant les possibilités de script de Jinja2, avec une syntaxe assez semblable à celle de 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>

À l'appel de render_template, vous devez fournir deux variables "colonnes" contenant une liste de colonnes de lignes et "éléments" contenant les lignes.

Pas besoin d'utiliser JS.

Si vous souhaitez prendre en charge certains types de données spéciaux, tels que les liens, vous pouvez le faire en utilisant des instructions if dans le modèle.

Voir la référence de Jinja2 pour plus de détails: http://jinja.pocoo.org/docs/2.10/templates/

3
Juergen

Vous pourriez également être intéressé par ce modèle, en utilisant des pandas de paquets Python:

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)

puis dans le page.html inclure les éléments suivants:

{{ table_html | safe }}

vous devez inclure le filtre safe afin qu’il restitue le code HTML brut sans échapper aucun des caractères.

Cela rendra ce qui suit, que vous pouvez également styliser avec les arguments et le Styler disponibles dans les 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, cela est également pratique pour les problèmes où vous avez une mise en forme conditionnelle complexe ou dynamique, il est plus facile de styler côté serveur python/pandas sans avoir à vous soucier du modèle html. Bien sûr, cela dépend de ce que vous faites, mais je soutiens que cela est plus facile à maintenir dans certaines situations - comme la mienne!

4
Attack68

J'ai modifié la réponse de @juegern pour travailler avec les balises <a> et maintenant mon code a l'air si

<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 permettant d'appliquer certaines données à cette table à partir de Flask: columns = [{'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)

0
crinny