Intérêt des templates

Pour nous aider à afficher les données de façon plus structurée, Django fournit un système de templating intégré au framework.

Les développeurs peuvent s’il le souhaitent utiliser d’autres systèmes de templates, comme Jinja2 un peu plus répandu, mais le système de templates de Django est assez complet et possède une syntaxe volontairement épurée.

Les bases de l’interface client

Pour commencer, présentons une simple liste des taches en utilisant un template défini dans une chaine de caractères :

dans le fichier lesTaches/views.py, ajoutons :

from lesTaches.models import Task # import de la class Task
from django.shortcuts import render # import de la methode render

def task_listing(request):
        from django.template import Template,Context
        objets=Task.objects.all().order_by('due_date')
        template=Template('{% for elem in objets %} {{elem}} <br />{%endfor%}')
        print(str(template))
        context=Context({'objets':objets})
        print(str(template.render(context)))
        return HttpResponse(template.render(context))

Pour que vous puissiez visualiser votre liste il faut modifier le fichier lesTaches/urls.py en y ajoutant une route :

path('listing', views.task_listing,name="listing"),

Testez sur l’URL localhost:8000/lesTaches/listing si votre serveur est toujours actif.

Cette solution, si elle est operationnelle, est un bien limitée et nous allons donc l’améliorer en utilisant des templates dans des fichiers séparés.

Commençons par créer un répertoire templates dans notre application lesTaches :

cd lesTaches
mkdir  templates

Par défaut, Django recherche les templates dans les dossiers templates de chaque app de votre projet.

Maintenant, il ne nous reste plus qu’à écrire le fichier template list.html dans le répertoire lesTaches/templates/

Pour utiliser le fichier list.html, on modifiera la vue en utilisant la fonction render() comme suit :

from lesTaches.models import Task
from django.shortcuts import render

def task_listing(request):
        tasks = Task.objects.all().order_by('due_date')
        return render(request,template_name='list.html',context={'tasks':tasks})

avec list.html :

{% block content %}
<h1>Liste des tâches</h1>
<ul>
{% for task in tasks %}
        <li>{{task}}</li>
{% endfor %}
</ul>
{% endblock %}

Héritage de templates

Pour uniformiser nos pages nous allons créer une page de base dont hériterons les différentes pages de notre app. Voici un exemple nommé baseLayout.html, que nous pouvons déposer dans le dossier templates de notre app, tandis que nos ressources statiques (css, js, images, etc.) sont à placer dans le dossier static de notre app.

On utilise dans notre template la commande load static, et on préfixe les adresses des ressources statiques du mot-clé static :

<!DOCTYPE html>
{% load static %}
<html lang="fr" >
<head>
        <meta charset="utf-8" >
        <title>
                {% block title %}{% endblock %}
        </title>
        <link rel="stylesheet" href="{% static css/mon.css %}" >
</head>
<body>
        <header>
        <h2> Gestion des Taches </h2>
        </header>

        <section>
                {% block content %}
                {% endblock %}
        </section>

        <footer>
                <em>Copyright IUT O, 2049</em>
        </footer>
</body>
</html>

Django utilise un système de templates volontairement doté d’une syntaxe simplifiée (par rapport à d’autres systèmes de templates un peu plus sophistiqués commes Jinja2 en Python ou Twig en PHP). La page est structurée de façon classique et nous avons utilisé la syntaxe des templates django pour créer deux blocs vides (titre et content) Ces deux blocs seront mis en place et remplis par les templates héritant de modeleBase.html comme par exemple list.html

Rappelons que dans le fichier views.py nous avons défini la fonction :

def task_listing2(request):
        objets = Task.objects.all().order_by('-due_date')
        # - (inverse l'ordre )
        return render(request,template_name='list.html', context={'taches':objets})

Nous voyons que l’on passe à la fonction render() un dictionnaire et un template (list.html) Ce sont les données de ce dictionnaire que l’on va pouvoir utiliser dans ce template list.html. Nous commençont par déclarer que list.html hérite de notre template baselayout.html :

{% extends 'baseLayout.html' %}
{% block title %} Liste {% endblock %}
{% block content %}
<h3>Tâches en cours ou terminées</h3>
<ul>
{% for  tache in taches %}
        <li>
        <h3>
        {% if tache.closed %}
                <span class="closed">{{tache.name}}</span>
        {% else %}
                {{tache.name}}
        {% endif %}
        </h3>
        <h4>{{tache.description }} </h4>
        <p>
        Date de rendu: {{tache.colored_due_date}}
        </p>
        <p>
        Date de debut: {{tache.schedule_date}}
        </p>
        </li>
{% endfor %}
</ul>
{% endblock %}
</html>

Vous pouvez constater que :

  • l’on a fait hériter notre template de baseLayout.html

  • nous avons donné un contenu au bloc titre

  • nous avons complété le bloc content.

  • les objets définis dans la fonction task_listing2 se retouvent ici dans le mots clé taches qui était justement l’index des objets dans le dictionnaire.

On parcourt l’ensemble des taches par une boucle for et pour chaque tache on effectue le traitement souhaité.

Template générique

Les templates sont cherchés par défaut dans les dossiers templates de chacune des app qui composent notre projet mais peuvent aussi être placées dans le dossier templates situé à la racine de notre projet.

Ce réglage permet de définir un template de base pour l’ensemble de notre projet dont peuvent hériter les templates des différentes apps. Pour cela nous devons autoriser l’usage d’un dossier templates à la racine du projet. Modifiez pour cela la clef DIRS dans la rubrique TEMPLATES du fichier settings.py :

TEMPLATES = [
{
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # 'DIRS': [],
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
        'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
        ],
        },
},
]

Ressources statiques

De même, les ressources statiques sont cherchées par défaut dans les dossiers static des apps. On peut vouloir ajouter des dossiers de ressources statiques globales pour le projet. On peut placer ces ressources dans un dossier static à la racine du projet en ajoutant de la même façon dans settings.py :

STATICFILES_DIRS = [
        os.path.join(BASE_DIR, "static"),
]

Nous pourrons ensuite déposer des ressources statiques communes (JS, CSS, Images, favicons, etc.) dans le dossier static placé à la racine du projet.