Jinja2 - Templates - Héritage

Dans les projets web, les applications comportent souvent plusieurs pages ayant des éléments communs, comme une navigation, un pied de page ou des styles partagés. Répéter ces éléments dans chaque fichier HTML serait non seulement fastidieux, mais rendrait aussi le projet difficile à maintenir. C'est là que l'héritage des templates de Jinja2, le moteur utilisé par Flask, devient essentiel.

    6ttr 5ttr
  • Intérmédiaire

Cet article approfondit le concept d'héritage dans Jinja2, en expliquant ses bases, ses avantages, et en fournissant des exemples détaillés pour créer des templates dynamiques et bien structurés.


Introduction à l'héritage des templates

L'héritage permet de définir une structure de base commune dans un template principal (par exemple, un en-tête, une navigation, un pied de page) et de laisser les templates enfants modifier ou compléter certaines parties spécifiques (comme le contenu d'une page).

Principe fondamental

  1. Template de base : Définit les blocs génériques, qui peuvent être personnalisés par les templates enfants.
  2. Template enfant : Hérite de la structure du template de base, remplit les blocs et peut ajouter du contenu ou modifier les parties existantes.

Pourquoi utiliser l'héritage ?

  1. Réduction des répétitions : Les éléments communs (entête, pied de page) sont définis une fois dans un template de base.
  2. Maintenabilité : Une modification dans le template de base est automatiquement répercutée sur toutes les pages enfants.
  3. Organisation : Chaque template enfant se concentre uniquement sur sa logique spécifique, en s’appuyant sur une structure commune.

Syntaxe de base de l'héritage

  1. Créer un template de base : Utilisez des blocs Jinja2 pour définir les parties modifiables.
  2. Créer un template enfant : Héritez du template de base avec {% extends %} et remplissez les blocs avec {% block %}.

Étape 1 : Créer un Template de Base

Le template de base définit une structure commune à toutes les pages. Par exemple, base.html peut inclure une en-tête, une navigation, un pied de page, et des blocs pour le contenu spécifique.

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Titre par défaut{% endblock %}</title>
    <link rel="stylesheet" href="/static/styles.css">
</head>
<body>
    <header>
        <h1>Mon Application</h1>
        <nav>
            <ul>
                <li><a href="/">Accueil</a></li>
                <li><a href="/about">À propos</a></li>
                <li><a href="/contact">Contact</a></li>
            </ul>
        </nav>
    </header>
    <main>
        {% block content %}
        <p>Contenu par défaut</p>
        {% endblock %}
    </main>
    <footer>
        <p>&copy; 2024 Mon Application</p>
    </footer>
</body>
</html>

Explications

  • {% block title %} : Déclare un bloc modifiable pour le titre de la page.
  • {% block content %} : Déclare un bloc modifiable pour le contenu principal.
  • Structure commune : Les balises <header> et <footer> restent identiques pour toutes les pages.

Étape 2 : Créer un Template Enfant

Un template enfant hérite de base.html en utilisant {% extends 'base.html' %} et remplit les blocs déclarés.

Exemple : Page d'accueil (index.html)

{% extends 'base.html' %}

{% block title %}Accueil{% endblock %}

{% block content %}
<h2>Bienvenue sur la page d'accueil</h2>
<p>Ceci est le contenu principal de la page d'accueil.</p>
{% endblock %}

Exemple : Page "À propos" (about.html)

{% extends 'base.html' %}

{% block title %}À propos{% endblock %}

{% block content %}
<h2>À propos de nous</h2>
<p>Nous sommes une équipe passionnée par le développement web.</p>
{% endblock %}

Étape 3 : Ajouter des Blocs Optionnels

Vous pouvez déclarer des blocs optionnels dans le template de base pour des parties qui ne sont pas toujours nécessaires.

Exemple avec une Barre Latérale (base.html)

Ajoutez un bloc pour une barre latérale :

<aside>
    {% block sidebar %}
    <p>Pas de contenu supplémentaire ici.</p>
    {% endblock %}
</aside>

Template Enfant avec Barre Latérale

{% extends 'base.html' %}

{% block title %}Page avec barre latérale{% endblock %}

{% block content %}
<h2>Contenu Principal</h2>
<p>Voici le contenu principal de cette page.</p>
{% endblock %}

{% block sidebar %}
<h3>Liens utiles</h3>
<ul>
    <li><a href="#">Lien 1</a></li>
    <li><a href="#">Lien 2</a></li>
</ul>
{% endblock %}

Étape 4 : Combiner des Blocs avec du Contenu Statique

Un template enfant peut ajouter du contenu sans remplacer entièrement un bloc.

Exemple : Ajouter du Contenu à un Bloc (base.html)

<header>
    <h1>Mon Application</h1>
    {% block header_extras %}
    {% endblock %}
</header>

Template Enfant qui Ajoute du Contenu

{% extends 'base.html' %}

{% block header_extras %}
<p>Slogan : Apprenez à coder avec nous !</p>
{% endblock %}

Étape 5 : Réorganiser avec des Fichiers Partiels

L’héritage peut être combiné avec des inclusions pour organiser les templates en fragments réutilisables.

Créer des Fichiers Partiels

Déplacez les parties répétitives dans des fichiers partiels, par exemple, un fichier _header.html :

<header>
    <h1>Mon Application</h1>
    <nav>
        <ul>
            <li><a href="/">Accueil</a></li>
            <li><a href="/about">À propos</a></li>
            <li><a href="/contact">Contact</a></li>
        </ul>
    </nav>
</header>

Inclure dans le Template de Base

Utilisez {% include %} pour insérer le fichier partiel dans base.html :

<body>
    {% include 'partials/_header.html' %}
    <main>
        {% block content %}
        <p>Contenu par défaut</p>
        {% endblock %}
    </main>
    <footer>
        <p>&copy; 2024 Mon Application</p>
    </footer>
</body>

Étape 6 : Gestion des Blocs Vides

Pour éviter des blocs vides non gérés, vous pouvez fournir des valeurs par défaut dans les templates de base.

Exemple : Bloc avec Valeur par Défaut

{% block sidebar %}
<p>Aucun contenu supplémentaire n'a été défini.</p>
{% endblock %}

Les templates enfants peuvent laisser ce bloc vide sans générer d’erreur.


Exemple Complet

Structure du Projet

projet/
│
├── templates/
│   ├── base.html
│   ├── index.html
│   ├── about.html
│   └── partials/
│       └── _header.html
│
├── static/
│   └── styles.css
│
└── app.py

Code Flask

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/about')
def about():
    return render_template('about.html')

if __name__ == '__main__':
    app.run(debug=True)

Bonnes Pratiques pour l’Héritage de Templates

  1. Structurez vos templates :

    • Créez un fichier base.html avec la structure commune.
    • Utilisez des fichiers partiels pour les éléments réutilisables.
  2. Nommez vos blocs clairement :

    • Utilisez des noms explicites pour éviter la confusion (par exemple, content, sidebar, header_extras).
  3. Évitez la surcharge :

    • Ne multipliez pas les blocs inutiles dans base.html. Concentrez-vous sur les parties vraiment dynamiques.
  4. Testez les blocs vides :

    • Fournissez des valeurs par défaut dans les blocs pour éviter les erreurs dans les pages enfants.

Conclusion

L’héritage des templates dans Jinja2 est une fonctionnalité puissante qui facilite la gestion de la structure et du contenu dans les applications Flask. Il améliore la réutilisabilité, réduit la répétition de code et simplifie la maintenance. En combinant héritage, inclusions, et bonnes pratiques, vous pouvez développer