Exemple de WAD adaptatif avec Bootstrap et Django

11.2 Exemple de WAD adaptatif avec Bootstrap et Django

Objectifs d'apprentissage

À la fin de cette section, vous serez capable de :

  • Créer une application web Todo avec Bootstrap et Django
  • Créer un projet Django
  • Créer et enregistrer une application Todo
  • Définir le modèle Todo
  • Mettre en place les API REST de Django
  • Créer l'interface utilisateur

Dans ce module, vous allez créer une application Todo simple et adaptative. Pour ce faire, vous utiliserez Bootstrap et Django. Bootstrap est un cadriciel d'application web adaptatif et à code source ouvert, et Django est un cadriciel de développement d'applications web basé sur Python. Ces deux cadriciels sont très populaires en raison de leur facilité d'utilisation.

Création d'une application web Todo avec Bootstrap et Django

L'application web Todo de cette sous-section utilise Bootstrap et Django. Les modèles CSS de Bootstrap sont utilisés pour les fonctionnalités de l'interface utilisateur. Django sert à la fois de frontal et de dorsal. Les modèles Django font partie de l'interface utilisateur pour obtenir et définir des données via des requêtes HTTP. Les requêtes entrantes sont ensuite traitées par une API construite à l'aide du Django REST Framework.

Prérequis

Pour construire l'application Todo, vous devez installer Python, PIP, Django, Django REST Framework, Bootstrap et jQuery. L'application Todo présentée dans les pages suivantes a été développée et testée avec des versions logicielles spécifiques. Pour éviter les erreurs, veuillez vous assurer d'installer les mêmes versions : Python v3.9.4, PIP v21.3.1, Django v4.0.1, Django REST Framework v3.13.1, Bootstrap v4.5.0 et jQuery v3.5.1.

Les étapes pour construire l'application Todo sont les suivantes :

  • Installer et configurer un environnement de programmation local pour Python 3.
  • Télécharger et installer Python 3.9.4.
  • Figure 11.14 montre comment ajouter Python et son sous-dossier Scripts à vos données d'environnement de chemin (sous Windows, les mises à jour de chemin pourraient être : C:\Users\your_username\AppData\Local\Programs\Python\Python39 et C:\Users\your_username\AppData\Local\Programs\Python\Python39\Scripts).
    La fenêtre d'édition des variables d'environnement montre l'ajout des dossiers Python et Scripts.
    Figure 11.14 C'est ce qui apparaît lors de l'ajout des dossiers Python et Scripts au chemin des variables d'environnement sous Windows. (Utilisé avec l'autorisation de Microsoft.)
  • Créer un environnement virtuel Python (venv) :
    $ python -m venv py394venv
  • Activer l'environnement virtuel :
    $ cd py394venv
    Windows: $ .\Scripts\activate.bat
    macOS: $ source ./bin/activate
  • Installer Django dans l'environnement de programmation local :
    $ pip install Django==4.0.1
  • Installer Django REST Framework dans l'environnement de programmation local :
    $ pip install djangorestframework==3.13.1]

Figure 11.15 montre la séquence des étapes nécessaires pour installer l'environnement Python afin de travailler avec Django et le Django REST Framework.

Séquence des étapes nécessaires pour installer l'environnement Python.
Figure 11.15 Cette capture d'écran affiche la séquence des étapes nécessaires pour installer l'environnement Python. (Utilisé avec l'autorisation de Microsoft)

Création du projet Django

La première étape pour construire une application web Django est de créer un projet Django (Django project), qui est un répertoire de haut niveau utilisé pour contenir les répertoires et les fichiers nécessaires à l'exécution d'une application web Django. Pour créer un projet Django, exécutez les commandes suivantes :

$ mkdir BootstrapDjangoToDoApp
$ cd BootstrapDjangoToDoApp
$ django-admin startproject ToDoApp.

Le point à la fin de la dernière commande est très important pour s'assurer que les fichiers dépendants de Django sont générés dans le répertoire actuel. En suivant ces commandes, le répertoire BootstrapDjangoToDoApp/ sera créé et les fichiers dépendants de Django seront générés comme le montre la Figure 11.16.

Le répertoire BootstrapDjanoToDoApp inclut les fichiers dépendants de Django : _pycache_, static, _init_.py, asgi.py, settings.py, urls.py, wsgi.py, db.sqlite3, manage.py.
Figure 11.16 Le répertoire BootstrapDjangoToDoApp/ inclut ces fichiers dépendants de Django. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Les tables de base de données intégrées de Django sont utilisées pour gérer les utilisateurs, les groupes, les migrations, etc., dans une application web. Pour générer ces tables, exécutez la commande migrate :

$ python manage.py migrate

La dernière étape pour créer un projet Django est de confirmer que la configuration a été effectuée. Pour ce faire, exécutez la commande runserver présentée ici :

$ python manage.py runserver

Pour confirmer davantage que la configuration du projet Django a été effectuée, lancez un navigateur et accédez à http://localhost:8000. La Figure 11.17 montre la page Django.

Page Django affichée une fois la configuration du projet terminée : L'installation a réussi ! Félicitations !
Figure 11.17 Une fois la configuration du projet Django terminée avec succès, cette page devrait apparaître à http://localhost:8000. (source : Django est une marque déposée de la Django Software Foundation.)

Création et enregistrement de l'application Todo

Une fois le projet Django terminé et configuré avec succès, l'étape suivante consiste à créer l'application Todo et à l'enregistrer dans le projet Django. Pour ce faire, exécutez la commande suivante :

$ python manage.py startapp todo

Le répertoire todo/ sera généré sous le répertoire du projet Django, BootstrapDjangoToDoApp/. Les fichiers liés à l'application Todo seront générés comme le montre la Figure 11.18.

Répertoire Todo/ généré sous le répertoire du projet Django : _pycache_, migrations, static, _init_.py, admin.py, apps.py, models.py, tests.py, urls.py, views.py.
Figure 11.18 Ceci montre le répertoire todo/, qui est généré sous le répertoire du projet Django, BootstrapDjangoToDoApp/. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Ensuite, l'application Todo doit être enregistrée dans le projet Django en tant qu'application installée afin que Django puisse la reconnaître. Pour ce faire, ouvrez le fichier ToDoApp/settings.py. Recherchez la variable INSTALLED_APPS comme le montre la Figure 11.19. Ajoutez 'todo' à la liste comme indiqué. Étant donné que le Django REST Framework sera utilisé, ajoutez également 'rest_framework' à la liste.

Une liste d'applications installées inclut 'rest_framework' et 'todo'.
Figure 11.19 Pour enregistrer l'application Todo dans le projet Django en tant qu'application installée, la liste des applications installées doit inclure 'rest_framework' et 'todo'. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Définir le modèle Todo

Une fois l'application web Todo enregistrée et installée, vous pourrez créer des tâches Todo, auxquelles des catégories peuvent être attribuées. L'étape suivante consiste à créer les modèles. Deux modèles seront créés pour Category et TodoList. Ouvrez le fichier todo/models.py et ajoutez le code présenté.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models
from django.utils import timezone

# Create your models here.
class Category(models.Model):

  name = models.CharField(max_length=100)

  class Meta:
    verbose_name = ("Category")
    verbose_name_plural = ("Categories")

  def __str__(self):
    return self.name

class TodoList(models.Model):
  title = models.CharField(max_length=250)
  content = models.TextField(blank=True)
  created = models.DateField(default=timezone.now().strftime("%Y-%m-%d"))
  due_date = models.DateField(default=timezone.now().strftime("%Y-%m-%d"))
  category = models.ForeignKey(Category, default="General", on_delete=models.DO_NOTHING)
  class Meta:
    ordering = ["-created"] # order by most recently created
  def __str__(self):
    return self.title

Les classes Python Category et TodoList décrivent les propriétés des modèles pour les tables Category et TodoList, respectivement. Le modèle TodoList contient un champ ForeignKey vers le modèle Category. Chaque élément Todo sera associé à une catégorie. Après avoir créé les modèles, un fichier de migration doit être généré pour créer les tables physiques dans la base de données. Pour générer le fichier de migration, exécutez la commande suivante :

    $ python manage.py makemigrations todo
    

Cette commande générera un fichier de migration dans todo/migrations/, qui ressemblera au code suivant.

# Generated by Django 4.0.1 on 2022-01-30 21:14

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

  initial = True

  dependencies = [
  ]

  operations = [
     migrations.CreateModel(
        name='Category',
        fields=[
           ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
           ('name', models.CharField(max_length=100)),
        ],
        options={
           'verbose_name': 'Category',
           'verbose_name_plural': 'Categories',
        },
     ),
     migrations.CreateModel(
        name='TodoList',
        fields=[
           ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
           ('title', models.CharField(max_length=250)),
           ('content', models.TextField(blank=True)),
           ('created', models.DateField(default='2022-01-30')),
           ('due_date', models.DateField(default='2022-01-30')),
           ('category', models.ForeignKey(default='General', on_delete=django.db.models.deletion.DO_NOTHING, to='todo.category')),
        ],
        options={
           'ordering': ['-created'],
        },
     ),
  ]

L'étape suivante consiste à appliquer les modifications du fichier de migration à la base de données, ce qui est réalisé en exécutant la commande suivante :

$ python manage.py migrate

Pour cette application, Django utilise la base de données sqlite3 (db.sqlite3) par défaut. Veuillez noter que Django prend également en charge d'autres bases de données, notamment MySQL et PostgreSQL. Pour définir le modèle Todo, vous pouvez utiliser l'interface d'administration Django par défaut pour effectuer des opérations CRUD sur la base de données. Pour utiliser l'interface d'administration, ouvrez le fichier todo/admin.py et enregistrez les modèles comme indiqué dans l'extrait de code suivant.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib import admin
from . import models

# Register your models here.
class TodoListAdmin(admin.ModelAdmin):
  list_display = ("title", "created", "due_date")

class CategoryAdmin(admin.ModelAdmin):
  list_display = ("name",)

admin.site.register(models.TodoList, TodoListAdmin)
admin.site.register(models.Category, CategoryAdmin)

L'étape suivante consiste à créer un compte superutilisateur qui permet d'accéder à l'interface d'administration. Pour ce faire, exécutez la commande suivante et suivez les invites pour saisir un nom d'utilisateur, une adresse e-mail et un mot de passe pour le superutilisateur.

$ python manage.py createsuperuser

Une fois cette étape terminée, redémarrez le serveur en utilisant la commande suivante :

$ python manage.py runserver

Une fois cette opération terminée, ouvrez un navigateur et accédez à http://localhost:8000/admin/. Pour accéder à l'interface d'administration, connectez-vous avec les identifiants que vous avez configurés pour le superutilisateur. Lorsque vous vous connectez à l'interface d'administration, vous devriez voir la page suivante de la Figure 11.20. Sur cette page, vous aurez la possibilité de créer, modifier et supprimer des catégories et des éléments Todo.

L'interface d'administration de Django affiche les outils d'administration du site pour créer, modifier et supprimer des catégories et des éléments Todo.
Figure 11.20 L'interface d'administration est l'endroit où les superutilisateurs peuvent créer, modifier et supprimer des catégories et des éléments Todo dans l'application web Todo. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Mise en place des API REST de Django

Précédemment, vous avez installé le Django REST Framework, qui fournit une boîte à outils pour construire des API. Dans cette section, vous allez créer les sérialiseurs, les fonctions de vue (View) et les routeurs nécessaires pour l'API.

Création des sérialiseurs

L'étape suivante consiste à implémenter deux sérialiseurs, un pour le modèle Category et un pour le modèle TodoList. Un sérialiseur (serializer) est un outil pour contrôler les sorties de réponse et convertir des données complexes en contenu, tel que JSON. Dans le répertoire todo/, créez le fichier serializers.py et ajoutez le code présenté dans l'extrait de code suivant. Les classes de sérialiseurs héritent de serializers.ModelSerializer car cette classe crée le sérialiseur, avec des champs correspondant aux champs du modèle définis précédemment. Chaque sérialiseur spécifie le modèle avec lequel travailler et les champs à inclure dans l'objet JSON, qui sont tous les champs.

# todo/serializers.py

from rest_framework import serializers
from .models import TodoList, Category

class CategorySerializer(serializers.ModelSerializer):
  class Meta:
    model = Category
    fields = "__all__"

class TodoSerializer(serializers.ModelSerializer):
  class Meta:
    model = TodoList
    fields = "__all__"

Création de la vue

Après avoir créé chaque sérialiseur, l'étape suivante consiste à créer une fonction de vue correspondante pour le sérialiseur Category et le sérialiseur Todo. Pour ce faire, ouvrez todo/views.py et ajoutez le code présenté dans l'extrait de code suivant. La classe viewsets, qui fournit une implémentation par défaut des opérations CRUD, est importée de rest_framework. Les classes CategoryView et TodoView fournissent un queryset de catégories et d'éléments Todo, respectivement. Elles spécifient également la serializer_class définie dans la section précédente.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render,redirect
from rest_framework import viewsets
from .serializers import TodoSerializer, CategorySerializer
from .models import TodoList, Category
import datetime

# Create your views here.

class CategoryView(viewsets.ModelViewSet):
  queryset = Category.objects.all()
  serializer_class = CategorySerializer

class TodoView(viewsets.ModelViewSet):
  queryset = TodoList.objects.all()
  serializer_class = TodoSerializer

Création des routeurs

L'étape suivante consiste à créer les routeurs qui fournissent les chemins d'URL pour l'API. Pour ce faire, ouvrez le fichier todo/urls.py et ajoutez le code présenté dans l'extrait de code suivant :

from django.urls import path, include
#from todo import views as todo_views
from rest_framework import routers
from todo.views import *

router = routers.DefaultRouter()
router.register(r'categories', CategoryView, basename='Categories')
router.register(r'todos', TodoView, basename='Todos')

urlpatterns = [
  path('', index, name="TodoList"),
  path(r'api/', include(router.urls)),
]

Une fois cette étape terminée, lancez le serveur Django en utilisant la commande suivante :

    $ python manage.py runserver
    

Pour accéder à l'API, lancez un navigateur et accédez à http://127.0.0.1:8000/api/. Comme le montre la Figure 11.21, vous devriez voir deux chemins d'API listés, un pour les catégories et un autre pour les éléments Todo.

Capture d'écran des chemins d'API – un pour les catégories et un pour les éléments Todo.
Figure 11.21 Une fois les chemins d'URL pour l'API créés, deux chemins d'API sont listés : un chemin pour les catégories et l'autre pour les tâches Todo. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Les éléments Todo dépendent des catégories. Pour effectuer des opérations CRUD sur la table Category, cliquez sur le chemin d'API des catégories, comme le montre la Figure 11.22.

Capture d'écran de la liste des catégories avec le chemin d'API.
Figure 11.22 Le chemin d'API peut être utilisé pour effectuer des opérations CRUD sur la table Category. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Une fois que vous accédez à la page Liste des catégories, entrez un nom de catégorie dans le champ situé près du bas de la page et cliquez sur le bouton Post pour l'enregistrer. Vous pouvez ajouter d'autres noms de catégories. Une fois que vous avez enregistré chaque nom à l'aide du bouton Post, les catégories apparaîtront au format JSON, comme illustré à la Figure 11.23.

Capture d'écran du format JSON sur la liste des catégories.
Figure 11.23 La liste des catégories est créée au format JSON après l'enregistrement des noms de catégories. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Pour s'assurer que les catégories peuvent être mises à jour ou supprimées si nécessaire, la clé primaire, qui est « id », doit être incluse dans le chemin d'API (par exemple, /api/categories/{id}/). Par exemple, pour mettre à jour ou supprimer la catégorie avec id=3, le chemin d'API est /api/categories/3/. Comme le montre la Figure 11.24, une fois cette catégorie affichée sur la page Instance de catégorie, le bouton DELETE est visible en haut pour supprimer la catégorie. Si la catégorie doit être mise à jour, le bouton PUT visible près du bas peut être utilisé pour les mises à jour.

Capture d'écran de l'instance de catégorie affichant les boutons DELETE et PUT.
Figure 11.24 La page Instance de catégorie fournit les boutons DELETE et PUT, qui peuvent respectivement être utilisés pour supprimer ou mettre à jour une catégorie. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Ensuite, revenez à la racine de l'API. Cliquez sur le chemin d'API des tâches Todo pour voir, comme décrit à la Figure 11.25, qu'un élément Todo possède un champ Catégorie qui apparaît comme une liste déroulante de catégories. Les opérations CRUD peuvent également être effectuées sur la table TodoList. Cela sera fait ensuite via l'interface utilisateur à l'aide de modèles.

Capture d'écran de la liste Todo avec une catégorie déroulante affichant Travail et Personnel.
Figure 11.25 Une fois les routeurs créés, un élément Todo possède un champ Catégorie qui apparaît comme une liste déroulante de catégories, telles que « Travail » et « Personnel ». (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Création de l'interface utilisateur

Pour utiliser et contrôler l'application Todo, vous devez créer une interface utilisateur (UI). Cette section décrira les étapes à suivre pour ce faire.

Installation de Bootstrap

La première étape pour créer une UI est d'installer Bootstrap, qui, en tant que cadriciel d'application web adaptatif et à code source ouvert, peut être utilisé dans des applications web comme Django pour créer des UI. Pour installer Bootstrap dans une application Django, vous avez plusieurs options. Dans ce scénario, une méthode efficace consiste à télécharger les fichiers CSS et JS de Bootstrap et à les ajouter au répertoire static/, comme le montre la Figure 11.26. Pour ce faire, créez d'abord le répertoire static/ dans le répertoire du projet Django. De plus, pour installer jQuery, téléchargez le fichier JS et ajoutez-le au répertoire static/. Enfin, ajoutez un fichier CSS personnalisé pour inclure un style individuel dans l'application web Django.

Capture d'écran du répertoire static avec les fichiers css et js listés.
Figure 11.26 Une méthode efficace pour installer Bootstrap dans une application Django consiste à télécharger les fichiers CSS et JS de Bootstrap et à les ajouter au répertoire static/. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Après avoir ajouté les fichiers CSS et JS au répertoire static/, l'étape suivante consiste à ouvrir le fichier ToDoApp/settings.py, à naviguer jusqu'à la fin du fichier et à ajouter les variables de chemin présentées dans l'extrait de code suivant.

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/

STATIC_URL = 'static/'

PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')

Création de la vue

L'étape suivante consiste à créer la vue. La fonction de vue est nécessaire pour les pages de modèle, qui sont créées dans la section suivante. La fonction de vue est également nécessaire pour interagir avec la base de données afin de créer et de supprimer des éléments Todo.

Pour créer la vue, ouvrez le fichier todo/views.py et ajoutez le code présenté dans l'extrait de code suivant. Ce code prend un objet de requête HTTP. Si la méthode de requête est POST, un élément Todo est soit créé, soit supprimé, selon le bouton sur lequel on clique. Sinon, la méthode de requête est GET et les éléments Todo sont affichés à l'utilisateur.

def index(request): # index view
  todos = TodoList.objects.all() # query all todos with object manager
  categories = Category.objects.all() # get all categories with object manager
  if request.method == "POST": # check if request method is POST
    if "taskAdd" in request.POST: # check if request is to add a todo item
      title = request.POST["description"] # title
      date = str(request.POST["date"]) # date
      category = request.POST["category_select"] # category
      content = title + " -- " + date + " " + category # content
      Todo = TodoList(title=title, content=content, due_date=date, category=Category.objects.get(name=category))
      Todo.save() # save todo item
      return redirect("/") # reload page
    if "taskDelete" in request.POST: # check if request is to delete a todo
      checkedlist = request.POST["checkedbox"] # checked todos to be deleted
      for todo_id in checkedlist:
        todo = TodoList.objects.get(id=int(todo_id)) # get todo id
        todo.delete() # delete todo
  return render(request, "index.html", {"todos": todos, "categories":categories})

Création des modèles

La dernière étape pour construire une application web Django est de créer des modèles, qui sont des fichiers HTML pouvant également contenir du code Python intégré. Créez un fichier nommé style.css sous le répertoire /static/css et insérez le code présenté ici dans ce fichier. Les modèles abordés dans les sections suivantes nécessitent cette feuille de style.

/* basic reset */
*,
*:before,
*:after {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

/* app */
html {
  font-size: 100%;
}

body {
  background: #e6f9ff;
  font-family: "Open Sans", sans-serif;
}
/* super basic grid structure */
.container {
  width: 600px;
  margin: 0 auto;
  background: #ffffff;
  padding: 20px 0;
  -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
  box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
}

.row {
  display: block;
  padding: 10px;
  text-align: center;
  width: 100%;
  clear: both;
  overflow: hidden;
}

.half {
  width: 50%;
  float: left;
}

.content {
  background: #fff;
}

/* logo */
h1 {
  font-family: "Rokkitt", sans-serif;
  color: #666;
  text-align: center;
  font-weight: 400;
  margin: 0;
}

.tagline {
  margin-top: -10px;
  text-align: center;
  padding: 5px 20px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  color: #777;
}

/* inputs */
.inputContainer {
  height: 60px;
  border-top: 1px solid #e5e5e5;
  position: relative;
  overflow: hidden;
}

.inputContainer.last {
  border-bottom: 1px solid #e5e5e5;
  margin-bottom: 20px;
}

.inputContainer.half.last.right {
  border-left: 1px solid #efefef;
}

input[type="date"],
input[type="text"],
select {
  height: 100%;
  width: 100%;
  padding: 0 20px;
  position: absolute;
  top: 0;
  vertical-align: middle;
  display: inline-block;
  border: none;
  border-radius: none;
  font-size: 13px;
  color: #777;
  margin: 0;
  font-family: "Open Sans", sans-serif;
  font-weight: 600;
  letter-spacing: 0.5px;
  -webkit-transition: background 0.3s;
  transition: background 0.3s;
}

input[type="date"] {
  cursor: pointer;
}

input[type="date"]:focus,
input[type="text"]:focus,
select:focus {
  outline: none;
  background: #ecf0f1;
}

::-webkit-input-placeholder {
  color: lightgrey;
  font-weight: normal;
  -webkit-transition: all 0.3s;
  transition: all 0.3s;
}
::-moz-placeholder {
  color: lightgrey;
  font-weight: normal;
  transition: all 0.3s;
}
::-ms-input-placeholder {
  color: lightgrey;
  font-weight: normal;
  transition: all 0.3s;
}
input:-moz-placeholder {
  color: lightgrey;
  font-weight: normal;
  transition: all 0.3s;
}

input:focus::-webkit-input-placeholder {
  color: #95a5a6;
  font-weight: bold;
}

input:focus::-moz-input-placeholder {
  color: #95a5a6;
  font-weight: bold;
}

.inputContainer label {
  padding: 5px 20px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  color: #777;
  display: block;
  position: absolute;
}

button {
  font-family: "Open Sans", sans-serif;
  background: transparent;
  border-radius: 2px;
  border: none;
  outline: none;
  height: 50px;
  font-size: 14px;
  color: #fff;
  cursor: pointer;
  text-transform: uppercase;
  position: relative;
  -webkit-transition: all 0.3s;
  transition: all 0.3s;
  padding-left: 30px;
  padding-right: 15px;
}

.icon {
  position: absolute;
  top: 30%;
  left: 10px;
  font-size: 20px;
}

.taskAdd {
  background: #444;
  padding-left: 31px;
}

.taskAdd:hover {
  background: #303030;
}

.taskDelete {
  background: #e74c3c;
  padding-left: 30px;
}

.taskDelete:hover {
  background: #c0392b;
}

/* task styles */
.taskList {
  list-style: none;
  padding: 0 20px;
}

.taskItem {
  border-top: 1px solid #e5e5e5;
  padding: 15px 0;
  color: #777;
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.5px;
}

.taskList .taskItem:nth-child(even) {
  background: #fcfcfc;
}

.taskCheckbox {
  margin-right: 1em;
}

.complete-true {
  text-decoration: line-through;
  color: #bebebe;
}

.taskList .taskDate {
  color: #95a5a6;
  font-size: 10px;
  font-weight: bold;
  text-transform: uppercase;
  display: block;
  margin-left: 41px;
}

.fa-calendar {
  margin-right: 10px;
  font-size: 16px;
}

[class*="category-"] {
  display: inline-block;
  font-size: 10px;
  background: #444;
  vertical-align: middle;
  color: #fff;
  padding: 10px;
  width: 75px;
  text-align: center;
  border-radius: 2px;
  float: right;
  font-weight: normal;
  text-transform: uppercase;
  margin-right: 20px;
}

.category- {
  background: transparent;
}

.category-Personal {
  background: #2980b9;
}

.category-Work {
  background: #8e44ad;
}

.category-School {
  background: #f39c12;
}

.category-Cleaning {
  background: #16a085;
}

.category-Other {
  background: #d35400;
}

footer {
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  color: #777;
}

footer a {
  color: #f39c12;
}
/* custom checkboxes */
.taskCheckbox {
  -webkit-appearance: none;
  appearance: none;
  -webkit-transition: all 0.3s;
  transition: all 0.3s;
  display: inline-block;
  cursor: pointer;
  width: 19px;
  height: 19px;
  vertical-align: middle;
}

.taskCheckbox:focus {
  outline: none;
}

.taskCheckbox:before,
.taskCheckbox:checked:before {
  font-family: "FontAwesome";
  color: #444;
  font-size: 20px;
  -webkit-transition: all 0.3s;
  transition: all 0.3s;
}

.taskCheckbox:before {
  content: "\f096";
}

.taskCheckbox:checked:before {
  content: "\f14a";
  color: #16a085;
}
/* custom select menu */
.taskCategory {
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  padding-left: 16.5px; /*specific positioning due to difficult behavior of select element*/
  background: #fff;
}

.selectArrow {
  position: absolute;
  z-index: 10;
  top: 35%;
  right: 0;
  margin-right: 20px;
  color: #777;
  pointer-events: none;
}

.taskCategory option {
  background: #fff;
  border: none;
  outline: none;
  padding: 0 100px;
}

Le premier fichier de modèle est base.html, qui est le fichier qui inclut les liens vers Bootstrap et jQuery. Pour illustrer ces liens, un extrait du fichier base.html est présenté dans le code. La barre de navigation Bootstrap est implémentée dans ce fichier.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>TodoApp - Django</title>
    {% load static %}
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="/static/css/bootstrap.min.css" />
    <link
      rel="stylesheet"
      type="text/css"
      href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
    />
    <link
      rel="stylesheet"
      type="text/css"
      href="{% static 'css/style.css' %}"
    />
    <!-- jQuery -->
    <script
      type="text/javascript"
      src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
    <!-- Popper -->
    <script
      type="text/javascript"
      src="{% static 'js/popper.min.js' %}"></script>
    <!-- Bootstrap Core JavaScript -->
    <script
    type="text/javascript"
    src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
<script
</head>

<body>
  <nav class="navbar navbar-dark bg-dark justify-content-between">
    <a class="navbar-brand">ToDo</a>
    <form class="form-inline">
      <input
        class="form-control mr-sm-2"
        type="search"
        placeholder="Search"
        aria-label="Rechercher"
      />
      <button class="btn btn-outline-info my-2 my-sm-0" type="submit">
        Rechercher
        </button>
      </form>
    </nav>
    <div>{% block content %} {% endblock content %}</div>
  </body>
</html>

Le deuxième fichier de modèle est index.html, qui liste tous les éléments Todo existants et inclut le formulaire pour créer ou supprimer un élément Todo. Un extrait du fichier index.html est présenté dans le code suivant. Le fichier index.html étend également le modèle base.html, ce qui permet d'insérer la barre de navigation Bootstrap implémentée dans base.html dans cette page et dans toutes les pages qui l'étendent.

{% extends "./base.html" %} {% load static %} {% block content %}
 <div django-app="TaskManager">
  <div class="container mt-5">
   <div class="content">
    <h1>Liste des tâches Todo</h1>
    <!--<p class="tagline">Django Todo App</p>-->
    <form action="" method="post">
     {% csrf_token %}
     <!-- csrf token for basic security -->
     <div class="inputContainer">
       <input
        type="text"
        id="description"
        class="taskName"
        placeholder="What do you need to do?"
        name="description"
        required
       />
       <label for="description">Description</label>
      </div>
      <div class="inputContainer half last">
       <i class="fa fa-caret-down selectArrow"></emphasis>
       <select id="category" class="taskCategory" name="category_select">
        <option class="disabled" value="">Choisir une catégorie</option>
       {% for category in categories %}
       <option
        class=""
        value="{{ category.name }}"
        name="{{ category.name }}"
       >
        {{ category.name }}
       </option>
       {% endfor %}
      </select>
      <label for="category">Catégorie</label>
     </div>
     <div class="inputContainer half last right">
      <input type="date" id="dueDate" class="taskDate" name="date" />
      <label for="dueDate">Date d'échéance</label>
     </div>
     <div class="row">
      <button class="taskAdd" name="taskAdd" type="submit">
       <i class="fa fa-plus icon"></emphasis>Add task
      </button>
      <button
       class="taskDelete"
       name="taskDelete"
       formnovalidate=""
       type="submit"
       onclick="$('input#sublist').click();"
      >
       <i class="fa fa-trash-o icon"></emphasis>Delete Tasks
      </button>
     </div>
     <ul class="taskList">
      {% for todo in todos %}
      <!-- django template lang - for loop -->
      <li class="taskItem">
        <input
         type="checkbox"
         class="taskCheckbox"
         name="checkedbox"
         id="{{ todo.id }}"
         value="{{ todo.id }}"
        />
        <label for="{{ todo.id }}"
><span class="complete-">{{ todo.title }}</span></label>
        <span class="category-{{ todo.category }}"
         >{{ todo.category }}</span>
         >{{ todo.category }}</span
<strong class="taskDate"
><i class="fa fa-calendar"></emphasis>Created: {{todo.created}} - Due:
         >{{ todo.category }}</span
{{todo.due_date}}</strong>
        >{{ todo.category }}</span
       </li>
        {% endfor %}
       </ul>
       <!-- taskList -->
      </form>
     </div>
     <!-- content -->
    </div>
  <!-- container -->
</div>
{% endblock %}

La première étape pour accéder à l'application web Todo Django est de redémarrer le serveur Django en utilisant la commande suivante :

$ python manage.py runserver

Ensuite, lancez un navigateur et accédez à http://localhost:8000. La page mise en évidence à la Figure 11.27 devrait apparaître.

Capture d'écran de la liste Todo avec les sections Description, Catégorie et Date d'échéance, ainsi que les boutons Ajouter une tâche et Supprimer les tâches.
Figure 11.27 Une fois le serveur Django redémarré, cette page devrait apparaître à http://localhost:8000. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Pour créer une liste de tâches Todo, remplissez le formulaire et cliquez sur le bouton Ajouter une tâche comme le montre la Figure 11.28.

Capture d'écran de la liste Todo avec les sections Description, Catégorie, Date d'échéance ; les boutons Ajouter une tâche, Supprimer les tâches ; et Écrire un article sur la création d'une application web Django à côté d'un bouton Travail.
Figure 11.28 Cette figure montre comment la liste Todo devrait apparaître après avoir utilisé le bouton Ajouter une tâche pour créer une liste de tâches Todo. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

De plus, l'élément Todo devrait également être visible dans l'API qui a été créée. Cela devrait apparaître comme décrit à la Figure 11.29.

Capture d'écran de la liste Todo visible dans l'API.
Figure 11.29 Une fois l'élément Todo créé, il devrait être visible dans l'API. (rendu dans Django, une marque déposée de la Django Software Foundation ; source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)