Le langage de template de Django

Nous présentons sur cette page le moteur de templates de Django, un outil extrêmement puissant et pratique pour écrire des vues (templates) élégantes et efficaces.

Une petite merveille !

Le langage de templating offert par Django est sans aucun doute l'un de ses points forts face aux frameworks de même type. Élégant, puissant et très simple, le templating sous Django est un jeu d'enfant !

Les classiques : exploitation de variables de contexte

Comme tout langage de template (Smarty, Jade, FreeMaker…), le moteur de templating de Django permet de manipuler des variables au sein d'un contenu textuel.

Affichage d'une variable

Les variables sont repérées par des doubles accolades : {{ ma_variable }}.

Voici un extrait de template permettant d'afficher le contenu d'une variable name :

Code
Bonjour {{ name }} !
Rendu
Bonjour pascal !

Filtres

Le moteur de template de Django accepte un certain nombre de filtres lors de l'utilisation de variables. Ces filtres permettent d'appliquer des traitements de mise en forme aux variables, est sont invoqués à l'aide d'un pipe : {{ ma_variable|filtre }}.

Voici un exemple d'utilisation de filtre sur une variable person_name ayant pour valeur « pascal » (sans majuscule). Le filtre capfirst fourni par Django permet de convertir la première lettre de la valeur d'une variable en capitale.

Code
Bonjour {{ name|capfirst }} !
Rendu
Bonjour Pascal !

Itération sur une liste ou un dictionnaire

Il est très courant de devoir exploiter une variable de type liste ou dictionnaire. Les listes manipulées sont généralement des QuerySets, c'est à dire le résultat d'une requête en BDD. Bien souvent, il s'agit de parcourir les données pour les afficher, soit dans un tableau, soit dans une liste à puces…

Le langage de template de Django fournit à ce propos une boucle for simple et proche de celle proposée en Python (c'est à dire fondée sur le design pattern iterateur.). Exemple sur une liste persons valant ["Bob", "Jim", "Zébulon"] :

Code
<ul>
{% for person in persons %}
    <li>{{ person }}</li>
{% endfor %}
</ul>
Rendu
Bob
Jim
Zébulon

Conditions simples

Autre opération que l'on doit souvent réaliser dans un template : l'évaluation de conditions. Une structure conditionnelle simple est proposée par le langage de template de Django.

Imaginons que nous souhaitions nous assurer qu'une liste contient bien des valeurs avant de l'afficher :

{% if online_members %}
    <ul>
        {% for member in online_members %}
            <li>{{ member.name }}</li>
        {% endfor %}
    </ul>
{% else %}
    Personne n'est connecté.
{% endif %}

Autres outils

Pour une liste détaillée des fonctionnalités disponibles dans le langage, voyez la documentation officielle consacrée au langage de template de Django.

Extension de template

C'est une fonctionnalité extrêmement puissante et appréciable : les templates Django peuvent être réutilisés et spécialisés par d'autres templates.

Nous commençons par définir un template de base, par exemple :

mon_template_de_base.html
<!DOCTYPE html>
<html>
    <head>
        <title>{% block title %}Miage Scrum{% endblock %}</title>
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>

Chaque template Django est stocké dans un fichier dont l'extension est .html.

Vous remarquez que le template comporte des blocks : un block est une portion de contenu nommée. Notre template mon_template_de_base.html comporte ainsi deux blocks : title et body.

Ces blocks pourront être redéfinis dans les templates qui étendrons notre template mon_template_de_base.html.

Créons à présent un autre template qui étendra notre template de base. Pour cela, nous créons un nouveau fichier autre_template.html, dont la première ligne précisera le template de base à étendre :

autre_template.html
{% extends "mon_template_de_base.html" %}

Ce nouveau template ne contiendra que la surcharge des blocks définis dans le template de base. Complétons-le :

autre_template.html
{% extends "mon_template_de_base.html" %}

{% block title %}{{ page.title }}{% endblock %}
    
{% block body %}
    {{ page.content }}
{% endblock %}

Testez vos connaissances

Pourquoi ne peut-on pas écrire de code Python dans les templates Django ?
  • Parce que contrairement au reste du framework, le moteur de template n'est pas codé en Python mais en Cobol objet.
  • Cette affirmation est fausse : on peut écrire du code Python dans les templates Django (encore heureux, puisque Django est un framework Python !).
  • Parce que contrairement au reste du framework, le moteur de template n'est pas codé en Python mais en C++.
  • Parce que le code des templates n'est jamais interprêté.
  • Parce que seul le langage de templating de Django est interprêté dans les templates.
  • C'est un choix des concepteurs de Django, pour éviter que les programmeurs ne fassent trop de traitements dans les templates.
Qu'est-ce qu'un filtre de template en Django ?
  • Un mécanisme qui permet d'altérer le rendu d'une variable au sein du template.
  • Un système ingénieux permettant de modifier le template appelé à l'exécution.
  • Un mécanisme permettant de filtrer les résultats d'un QuerySet à afficher dans un template.
Si une variable copain_de_tchoupi existe dans le contexte et que sa valeur est "DOUDOU OU CAILLOU", qu'affichera cette instruction sur la page générée : {{ copain_de_tchoupi|lower|truncatewords:1|capfirst }}
  • DOUDOU OU CAILLOU
  • Frankenstein
  • Doudou Ou Caillou
  • Doudou ...
  • Doudou
  • Caillou
  • Tchoupi
  • Petit ours brun
Qu'est-ce que {{ copain_de_tchoupi|lower|truncatewords:1|capfirst }} ?
  • L'utilisation d'un filtre sur la variable lower.
  • L'utilisation d'un filtre sur la variable copain_de_tchoupi.
  • C'est du code invalide dans un contrôleur Django.
  • L'utilisation d'un tag de template sur la variable copain_de_tchoupi.
  • L'utilisation d'un tag de template sur la variable lower.
  • L'utilisation d'un tag de template sur la variable capfirst.
Dans {{ copain_de_tchoupi|lower|truncatewords:1|capfirst }}, qu'est-ce que :1 ?
  • Le numéro de ligne.
  • C'est un argument admis par le tag truncatewords.
  • C'est un argument admis par le filtre truncatewords.
  • C'est un filtre de template.
  • C'est ce qui permet de diviser le résultat par 1.

Si une variable notes existe dans le contexte, et que sa valeur est "EADGBE", qu'affichera le code suivant s'il est écrit dans le template mon_template.html ?

for note in notes:
    print(note)
  • E
    A
    D
    G
    B
    E
  • for note in "EADGBE": print(note)
  • E A D G B E
  • note
    note
    note
    note
    note
    note
  • Rien
  • EADGBE
  • Ce code provoquera une erreur de compilation.
  • Ce code provoquera une erreur d'interprétation.

Attention, le langage de template Django n'est pas du Python !

Si une variable notes existe dans le contexte, et que sa valeur est "EADGBE", qu'affichera le code suivant s'il est écrit dans le template mon_template.html ?

{% for note in notes %}
    note
{% endfor %}
  • E
    A
    D
    G
    B
    E
  • for note in "EADGBE": print(note)
  • E A D G B E
  • note
    note
    note
    note
    note
    note
  • Rien
  • EADGBE
  • Ce code provoquera une erreur de compilation.
  • Ce code provoquera une erreur d'interprétation.

Si une variable notes existe dans le contexte, et que sa valeur est "EADGBE", qu'affichera le code suivant s'il est écrit dans le template mon_template.html ?

{% for note in notes %}
    {{ note }}
{% endfor %}
  • E
    A
    D
    G
    B
    E
  • for note in "EADGBE": print(note)
  • E A D G B E
  • note
    note
    note
    note
    note
    note
  • Rien
  • EADGBE
  • Ce code provoquera une erreur de compilation.
  • Ce code provoquera une erreur d'interprétation.

Soit un modèle M possédant un champ name de type CharField. Soit un contrôleur C réalisant entre-autre l'instruction m_list = M.objects.all() et plaçant la variable m_list dans le contexte avant le rendu d'un template T. Dans le template T, on trouve la chose suivante :

{% for m in m_list %}
    {{ m }}
{% endfor %}

Le résultat affiché à l'écran est le suivant :

M object M object M object

Comment procéder pour que les noms (attribut name) des objets M soient affichés à la place de cette mascarade ?

  • Définir une méthode __unicode__() ou __str__() dans le contrôleur C.
  • Définir une méthode __unicode__() ou __str__() dans la classe M.
  • Redémarrer manuellement le serveur de dev de Django pour que les mises à jour soient prises en compte.
  • Utiliser des filtres dans le template T.

Soit un template nommé tpl.html, rendu avec dans le contexte une variable nom dont la valeur est "Guido van Rossum". Que se passe-t-il lors du rendu de ce template s'il contient les lignes suivantes :

{% extends "tpl.html" %}
            
Coucou {{ nom }}
  • Une erreur se produit car extends n'est pas un tag de template Django valide.
  • « Coucou Guido van Rossum » est affiché à l'écran.
  • « Coucou » est affiché à l'écran.
  • Une erreur se produit car un template ne peut s'étendre lui même.
  • Rien n'est affiché à l'écran.
  • Une erreur 404 est générée.