Les templates
Principes et généralités
Nous utilisons le mot anglais de template, car il est communément utilisé, répandu, et compris dans ce contexte par les professionnels. De plus, en cas de recherche sur le Web, il est plus facile de trouver la bonne information avec template qu’avec une traduction française. Pour mémoire, template peut être traduit ainsi : modèle/patron/gabarit.
Le principe général de fonctionnement d’un moteur de templates est le suivant : un fichier décrivant la structure de ce que l’on veut produire ou afficher va servir d’ossature ou de modèle. Le moteur (ou processeur) de templates va venir « habiller » ce squelette en fonction des données produites par le programme, le résultat sera une page dynamiquement générée. Concrètement, pour Django, c’est un fichier texte qui est rempli par le moteur de templates avec des variables générées par le framework afin de produire un document au format requis, le plus souvent HTML.
Schémas de principe :
Le principe mis en œuvre dans Django pour gérer des templates est donc, pour ceux qui connaissent déjà le principe, similaire à celui que l’on peut rencontrer dans d’autres langages/systèmes de templates, tels que Jinja2, HAML, OpenDoc, Mako, boiler plate, etc. Il y a cependant des spécificités propres aux templates Django, en particulier une excellente intégration avec l’ensemble du framework.
1. Intérêt des templates
Les principaux avantages apportés par ce type d’outil sont :
-
La séparation des préoccupations (respect du principe SoC), en particulier pour assurer la séparation entre le webdesign et la programmation.
-
Une grande flexibilité d’évolution de l’aspect du site, de sa présentation.
-
La facilité de « localisation » (adaptation à une langue) de l’interface du site.
-
La possibilité de faire travailler séparément et en même temps des personnes différentes sur la conception graphique et sur le code.
-
La normalisation et la standardisation des contenus et des affichages.
-
La réutilisation et la généricité du code produit....
Le principe et la syntaxe du langage de templates de Django
Un fichier de template Django est, comme vu précédemment, tout simplement un fichier texte dans lequel sont installées des balises spécifiques, permettant de générer à peu près n’importe quel format basé sur du texte (HTML, XML, CSV, etc.).
Un fichier de template Django contient des commentaires, des variables (variables qui seront remplacées à la volée par la valeur de la variable lors de l’évaluation du template) et des tags (instructions, mots-clefs ou étiquettes) qui contrôlent la logique du flux d’affichage du fichier template.
Les instructions, variables et commentaires sont délimités par trois balises : {{ .. }} pour les variables, {% ... %} pour les tags ou instructions et enfin {# ... #} pour les commentaires sur une même ligne.
Par la suite nous continuerons à utiliser le mot tag pour rester en cohérence avec la documentation Django. Rappelons qu’il s’agit d’une instruction, d’un mot-clef. Les tags proposés par le langage de templates Django fonctionnent de manière similaire aux instructions d’un langage de programmation. Ainsi, le tag if permet de traiter des expressions booléennes, le tag for permet de construire des boucles. Attention, ces différents tags ne sont pas exécutés de manière totalement similaire aux expressions Python correspondantes. De base, seuls les tags et les filtres décrits ci-après sont supportés. L’utilisateur pourra en ajouter, soit en installant des add-ons ou des applications complémentaires, soit en développant ses propres tags et filtres.
Du point de vue technique, les variables à destination du template sont stockées dans un dictionnaire Python appelé context (contexte), ce dictionnaire est passé en paramètre des fonctions de rendu des templates par le programmeur.
-
Les clefs du dictionnaire correspondent aux noms des variables qui seront accessibles lors de l’exécution du rendu du template.
-
La valeur associée à la clef est l’objet Python correspondant. Le contexte global de l’évaluation d’un template est composé du dictionnaire passé...
L’héritage dans les templates
Une des fonctionnalités puissantes du processeur de templates Django est l’héritage. Ce mécanisme permet de créer un modèle de base, un squelette, qui va contenir tous les éléments importants de votre site. Ces éléments étant définis sous forme de blocs nommés. Ces blocs vont pouvoir être modifiés, étendus ou supprimés par les templates enfants qui hériteront de ce modèle de base. Toutes les modifications pourront être faites bloc par bloc, en fonction des besoins du template enfant.
Pour signifier qu’un template enfant hérite de son parent on utilise le tag extends.
{% extends "nom_du_template_parent.html" %}
Important : le tag {% extends %}, s’il est utilisé dans un template, doit apparaître en premier, sinon cela ne fonctionnera pas !
Chaque nom de bloc ne peut être défini qu’une fois dans un template enfant, car sinon le moteur de templates ne saura pas lequel utiliser et renverra un message d’erreur.
On peut récupérer le contenu du bloc du template parent, grâce à la variable {{ block.super }}. Cela peut par exemple servir si l’on souhaite juste rajouter un peu de contenu au bloc du template parent sans avoir envie de tout réécrire, en particulier si ce bloc est long et complexe. Cette variable ne sera pas soumise à la procédure d’échappement automatique du HTML car le traitement correct aura déjà été fait lors de l’évaluation du bloc dans le template parent.
Le nombre de niveaux d’héritage n’est pas limité. Une façon courante d’utiliser ce principe est par exemple d’avoir un template base.html qui uniformise l’aspect du site, des templates différents en fonction des rubriques du site (templates qui héritent du template base.html) et enfin des pages qui héritent du template de leur rubrique. Ce mécanisme permet de maximiser la possibilité de réutiliser du code et de le partager entre différentes parties du site.
base.html
blog.html ...
Échappement automatique du HTML
Par échappement on entend remplacement de certains caractères spéciaux propres aux balises HTML par une valeur qui sera affichée comme du texte et non comme une balise. Par exemple le remplacement de ’<’ par ’<’. En effet lorsque l’on génère du HTML depuis un template à partir de variables, il y a toujours un risque que ces variables contiennent des caractères qui peuvent compromettre l’affichage du HTML. Le développeur ne maîtrise que le contenu des variables qu’il a générées lui même, or un site web moderne contient également des informations saisies par les utilisateurs (blogs, informations, réactions aux forums...) et sur lesquelles il n’a pas le contrôle.
Prenons un exemple :
Utilisateur {{user.nom}} connecté depuis le ....
Cela peut sembler anodin, car cette instruction va simplement afficher le nom de l’utilisateur, mais supposons que user.nom provienne d’un formulaire et que l’utilisateur en question ait rentré la valeur suivante pour son nom :
<script>mon_code_malveilant(){... </script>
Avec un tel nom, le template affichera le résultat suivant :
Utilisateur <script>function mon_code_malveilant(){... </script>
connecté depuis le ....
Ce qui pourrait provoquer des résultats inattendus ...
Il en est de même si le nom rentré est par exemple :
<div style="background-color:red;">Bob
qui affichera :
Utilisateur <div style="background-color:red;">Bob connecté depuis le ....
En dehors de probablement casser la mise en page, il va certainement y avoir beaucoup de rouge sur la page ce qui n’est pas exactement ce que l’on souhaite.
Aucune donnée venant de l’extérieur ne peut être considérée comme sans danger, et certains utilisateurs malveillants mettent cela à profit pour réaliser des attaques. Ce type de faille de sécurité est appelé une attaque XSS (Cross Site Scripting).
Pour éviter cela, on peut envisager trois possibilités :
-
Travailler...
Les librairies de tags et de filtres spécifiques
Certaines applications ou add-ons de Django fournissent des librairies de tags et filtres additionnels.
Si l’on souhaite les charger, il faut utiliser le tag load.
{% load librairie_de_tags %}
Si la librairie librairie_de_tags contient par exemple le tag ’tag_supplementaire’ attendant deux paramètres, alors le tag ci-dessous pourra être compris par le moteur de templates :
{% tag_supplementaire param1 param2 %}
Pour pouvoir être comprise, l’instruction load va chercher dans les applications installées de la façon suivante :
mysite/
settings.py
mon_app/
templatestags/
__init__.py
mes_tags.py
$PYTHON_PATH/lib/site-packages/module_tiers/
templatestags/
__init__.py
tags_du_module_tiers.py
INSTALLED_APPS = {
...
'mon_app',
'module_tiers,
...
}
Alors {% load mes_tags %} inclura les tags définis...
Les tags et les templates de base
Nous allons maintenant lister tous les tags et filtres de Django. Notons une possibilité particulièrement utile de l’outil d’administration de Django. Il inclut un gestionnaire automatique de documentation, qui permet de consulter les tags et filtres disponibles. Cela s’avère particulièrement intéressant si l’on a installé des applications ou des modules complémentaires, car ces tags et filtres additionnels ne sont décrits ni dans ce livre ni dans la documentation Django, mais seulement dans la documentation du module additionnel.
1. Les tags de base
Leur liste est donnée par ordre alphabétique :
autoescape (on | off )
Tag de type bloc se terminant par endautoescape.
Ce tag est expliqué en détail à la section Échappement automatique du HTML. Pour mémoire, ce tag contrôle l’état courant de l’échappement automatique du HTML. Il prend en paramètre ’on’ ou ’off’. ’on’ rétablissant le traitement automatique de l’échappement de chaînes HTML et ’off’ le désactivant. C’est un tag de bloc et il doit être fermé par endautoescape.
Lorsque autoescape est à on, cela revient à appliquer le filtre escape à chaque variable ; lorsqu’il est à off, cela revient à appliquer le filtre safe à chaque variable.
Attention, les variables déjà marquées comme sûres (safe) ne seront pas concernées par l’échappement HTML.
Exemple d’utilisation :
{% autoescape on %}
{{ variable }}
{% endautoescape %}
équivalent à : {{ variable|escape}}
block nom_du_bloc
Tag de type bloc se terminant par endblock [nom_du_bloc].
Définit un bloc nommé que les templates enfants peuvent remplacer. Pour comprendre, voir la section spécifique sur l’héritage dans les templates.
comment
Tag de type bloc se terminant par endcomment.
Tout ce qui est entre les tags comment et endcomment sera ignoré, que ce soit du texte, des balises HTML ou des tags et variables Django. Contrairement aux commentaires HTML, ces informations ne seront pas visibles dans le fichier...