Ceci est une ancienne révision du document !
Grossièrement, le template est une page web à trous. Il contient des sections statiques en HTML/javascript directement interprétables par le navigateur web et des section non remplies désignées placeholders. Le contenu des placeholders est généré par l'application à l'exécution pour obtenir un comportement dynamique.
Flask s'appuie sur le moteur Jinja2 pour la gestion des templates. Plusieurs éléments syntaxiques sont disponibles pour délimiter les sections à l'attention du moteur de templates :
{{ }} Affiche le résultat du code Python ;{% %} Code Python à interpréter ;{# #} Commentaires.<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>FlaskApp</title> </head> <body> {# Affiche le contenu de la variable msg comme titre #} <h1>{{ msg }}</h1> <h2>Welcome to FlaskApp!</h2> </body> </html>
Pour pouvoir générer la partie dynamique du template via le framework Flask, on utilise la fonction helper render_template(). Effectuer le rendu du template, c'est générer le contenu des placeholders pour produire une page web complète pouvant être retournée au client.
./templates de l'application.
from flask import Flask, render_template # ... @app.route('/') def supply_index() -> str: msg = "Hello World !!!" return render_template('index.html', msg=msg)
A l'intérieur des templates les objets suivants sont disponibles :
Les fonctions url_for() et get_flashed_messages() sont également disponibles.
Si les liens vers les autres pages sont définis en dur dans les templates, ils deviendront invalides lorsque les routes de l'application Flask seront modifiées.
C'est pourquoi il est recommandé d'utiliser la fonction helper url_for() pour définir les liens vers les autres pages/actions.
L'argument à fournir est un nom fonction associée à la vue ( associée à une route de l'application Flask).
Dans notre projet Flask, on a une fonction nommée par exemple create_universe :
@app.route('/create/universe', methods=['GET', 'POST']) def create_universe(): if request.method == 'POST': ...
Cette fonction est associée à la route /create/universe. Dans notre template si on souhaite créer le lien vers cette page on peut produire le code suivant :
... <a href="{{ url_for('create_universe') }}" class="active tm-paging-link">+</a> ...
La notion d'héritage appliquée au template va permettre de factoriser le code. La factorisation augmente la qualité du code et simplifie la maintenance.
base.html contenant la structure générale du site/application web ;Un exemple de document parent avec en surbrillance les placeholders :
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>{% block title %}{% endblock %}</title> <meta name="keywords" content="mot1, mot2, mot3, mot4"> <meta name="description" content="ma description de page ici"> <link rel="icon" type="image/png" href="/static/images/favicon-16x16.png" sizes="16x16"> <link rel="icon" type="image/png" href="/static/images/favicon-32x32.png" sizes="32x32"> <link rel="stylesheet" href="style.css"> </head> <body> <header> <!--contenu statique de l'entete --> </header> <nav> <!-- barre de navigation --> <a href="#">Accueil</a> <a href="#">Aide</a> <a href="#">A propos</a> </nav> <div class="content"> {% block content %}{% endblock %} </div> <footer> <!-- contenu statique du pied de page --> </footer> <script src="script.js"></script> </body> </html>
Un exemple de document enfant :
{% extends 'base.html' %}
{#
Hérite du template "base.html"
doit redéfinir les placeholders : "title" et "content"
#}
{% block content %}
<aside>
<!-- section messages flash -->
</aside>
<main>
<h1>{% block title %} Accueil {% endblock %}</h1>
<p>{{ msg }}</p>
</main>
<aside>
<!-- section status -->
</aside>
{% endblock %}
La définition de la route dans l'application Flask reste inchangée.
Le moteur de template supporte la boucle for avec la syntaxe suivante :
{% extends 'base.html' %}
{#
Hérite du template "base.html"
doit redéfinir les placeholders : title et content
#}
{% block content %}
<aside>
<!-- section messages flash -->
</aside>
<main>
<h1>{% block title %} Accueil {% endblock %}</h1>
<p>{{ msg }}</p>
<!-- Affiche tous les commentaires -->
<div style="width: 50%; margin: auto">
{% for comment in comments %}
<div style="padding: 10px; background-color: #EEE; margin: 20px">
<p style="font-size: 24px">{{ comment }}</p>
</div>
{% endfor %}
</main>
<aside>
<!-- section status -->
</aside>
{% endblock %}
La variable comments devra être fournie par la vue au template :
@app.route('/') @app.route('/home') def supply_index() -> str: msg = "Hello World !!!" comments = [ "commentaire 1", "commentaire 2", "commentaire 3", "commentaire 4", ] return render_template('index.html', msg=msg, comments=comments)
La structure conditionnelle if utilise la syntaxe suivante :
{% extends 'base.html' %}
{#
Hérite du template "base.html"
doit redéfinir les placeholders : title et content
#}
{% block content %}
<aside>
<!-- section messages flash -->
</aside>
<main>
<h1>{% block title %} Accueil {% endblock %}</h1>
<p>{{ msg }}</p>
<!-- Affiche tous les commentaires -->
<div style="width: 50%; margin: auto">
{% for comment in comments %}
{% if loop.index % 2 == 0 %}
{% set bg_color = '#e6f9ff' %}
{% else %}
{% set bg_color = '#eee' %}
{% endif %}
<div style="padding: 10px; background-color: {{ bg_color }}; margin: 20px">
<p style="font-size: 24px">{{ comment }}</p>
</div>
{% endfor %}
</main>
<aside>
<!-- section status -->
</aside>
{% endblock %}
Les filtres Jinja permettent d'appliquer des transformations/opérations sur les variables directement depuis les templates : on peut par exemple passer un texte en majuscules en appliquant le filtre upper. La syntaxe à utiliser est {{ var | filtre }}
<div style="padding: 10px; background-color: {{bg_color}}; margin: 20px"> <!-- Affiche le commentaire en majuscules --> <p style="font-size: 24px">{{ comment | upper }}</p> </div>
Le filtre safe est important à connaître : il permet d'autoriser l'interprétation du code HTML provenant des variables. En effet, par défaut, le code contenu dans les variables est échappé par le moteur Jinja2 pour éviter les attaques de type XSS1)
{# Ici les balises sont échappées par le moteur Jinja : elles seront affichées comme du texte #}
{{ "<h2>CECI NE PRODUIRA PAS UN SOUS-TITRE</h2>" }}
{# le filtre safe permet d'interpréter les balises et de produire un titre HTML #}
{{ "<h2>SOUS TITRE</h2>" | safe }}
Le plus simple est d'appeler la méthode strftime() sur l'objet de type datetime :
<div> <span>{{ universe.created_on.strftime('%d-%m-%Y') }}</span> </div>