04 Le Scaffolding avec Django
Le scaffolding est une fonctionnalité proposée par certains frameworks de développement, permettant de créer des interfaces d'administration en prenant en charge les fastidieuses interfaces de CRUD : création, lecture, mise à jour et suppression. Django possède une fonctionnalité de scaffolding très puissante.
Les CRUDs c'est chiant !
Quoi de plus ennuyeux que de développer des centaines de fois le même genre de fonctionnalité permettant de mettre à jour les données d'une application. Des formulaires pour créer des choses, les modifier, etc. Des tableaux pour visualiser des listes. Bref, rien de bien folichon.
Depuis très longtemps, les devs ont cherché à écrire des briques génériques permettant de prendre en charge ces fonctionnalités, sans avoir à réinventer la roue à chaque projet. C'est là qu'intervient le scaffolding.
Scaffolding de base
Vous l'avez compris depuis le début des TPs: Django est modulaire et tout fonctionne par applications. C'est donc tout naturellement que le scaffolding est une application sous Django. Nous allons vérifier que celle-ci (django.contrib.admin) est bien mentionnée dans la variable INSTALLED_APPS de notre fichier settings.py.
Pour l'utiliser nous avons besoin d'une URL que nous avons déjà paramétrer au TP précédent au sein du fichier urls.py (celui du projet). Il nous suffit donc de se rendre sur l'URL http://127.0.0.1:8000/admin.
Django gère pour vous les problématiques d'authentification relatives à ce genre d'interface (imaginez un peu une interface d'administration sans authentification ..). Afin de vous identifiez il va nous falloir créer un compte pour ce faire nous alons encore utiliser la ligne de commande:
$ python manage.py createsuperuser
Celle-ci est suffisament parlante pour ne pas avoir à décrire son fonctionnement.
Connectez-vous en entrant les identifiant/mot de passe que vous avez saisis lors de la création du compte. Vous devriez arriver sur l'écran d'accueil de votre interface d'administration :
Vous pouvez désormais administrer les comptes utilisateurs de votre projet.
Administration de notre application
Tout ceci est très sympathique, mais ce serait encore mieux si nous pouvions aussi mettre à jour les données relatives à notre application.
Pour cela, nous devons signaler à Django pour quels models nous voulons disposer d'une interface d'administration. Nous allons le faire en créant un fichier admin.py dans le répertoire de notre application games_review.
Placez-vous dans le répertoire de l'application games_review, et créez-y un fichier admin.py. Placez-y le contenu suivant :
from django.contrib import admin
from games_review.models import *
admin.site.register(Type)
admin.site.register(Game)
Si nous rafraîchissons notre interface d'administration:
Nous avons maintenant la possibilité d'administrer l'ensemble de nos objets métiers.
Pas mal n'est-ce pas ? Nous avons écrit une dizaine de lignes de code (de paramétrage), aucune logique (donc aucun bug), et nous disposons d'une application fonctionnelle pour l'administration de notre projet.
Paramétrage de la langue
Vous aurez remarqué que par défaut, notre interface d'administration est en anglais. C'est n'est pas un problème lorsque l'on est parfaitement bilingue comme un étudiant en LP RGI, mais ça peut être rebutant pour certains, notamment pour les utilisateurs potentiels de notre application .. Nous allons simplement spécifier à Django que nous souhaitons que la langue du projet soit le français.
Rien de plus simple : modifions notre fichier settings.py:
TIME_ZONE = 'Europe/Paris'
LANGUAGE_CODE = 'fr-FR'
Sauvegardez le fichier, et c'est terminé ! Notre back-office est à présent intégralement en français.
Les plus tatillons dirons « Hum, l'interface est en français, mais les noms de nos modèles restent en anglais… ». Certes. Pour fixer ceci, nous allons paramétrer nos modèles de manière à ce que leur nom affiché le soit en français :
class Type(models.Model):
name = models.CharField(max_length=150)
slug = models.SlugField()
class Meta:
verbose_name = 'Catégorie'
verbose_name_plural = 'Catégories'
Nous avons ici défini de quelle manière doit s'afficher le nom du modèle, à l'infinitif et au pluriel.
Personnalisation des listes
Dans toute interface d'administration, il est question de présenter des listes d'enregistrements (qui reflètent généralement les lignes des tables d'une base de données). Les back-offices générés par Django ne dérogent pas à cette règle.
On retrouve une présentation classique comportant une liste d'objets, un bouton d'ajout d'un nouvel objet, et la possibilité de sélectionner une ou plusieurs lignes pour y appliquer des actions (ex. : suppression).
Le problème est que la présentation de la liste n'est pas folichonne : chaque ligne est nommée « Game object », ce qui n'est absolument pas parlant. D'autre part, on aimerait disposer de quelques outils pratiques, notamment pour trier les objets, réaliser des recherche textuelles, etc. Voyons à présent comment mettre en place tout ceci.
Un nom parlant
Notre premier objectif est que Django n'affiche plus « Game object » comme ancre de lien vers la fiche d'un jeu, mais plutôt le nom de celui-ci. Pour cela, nous allons définir, dans notre modèle Game, une méthode str(), qui aura pour mission de retourner le nom à afficher pour un jeu donné:
Dans models.py ajoutez:
class Game(models.Model):
name = models.CharField(max_length=150)
slug = models.SlugField()
author = models.ForeignKey(User)
release_date = models.DateTimeField(auto_now_add=True)
picture = models.ImageField()
types = models.ManyToManyField(Type)
def __str__(self):
return self.name
Nous disposons désormais d'un affichage beaucoup plus lisible.
Gestion des colonnes
Pour l'instant une seule colonne est affichée. Nous souhaitons pouvoir consulter directement dans la liste d'autres informations sur nos jeux. Pour ce faire nous allons modifier le fichier admin.py de notre application games_review afin de surcharger quelques éléments de l'interface d'administration.
Pour chaque modèle pris en charge par le scaffolding de Django il est possible de définir une classe fille de ModelAdmin décrivant le comportement de l'interface d'administration.
games_review/admin.py:
class GameAdmin(admin.ModelAdmin):
list_display = ('name', 'release_date', )
Nous avons ici simplement spécifié à Django que la vue de liste doit comporter deux colonnes, name et release_date (les deux champs de notre modèle Game).
Il nous reste à lui demander de prendre en compte ce paramétrage, en précisant le nom de notre classe lors de la déclaration du modèle en tant que candidat à l'administration :
admin.site.register(Game, GameAdmin)
La liste compète des options est disponibles à cette adresse : section ModelAdmin options.
Un champ de recherche
Nous aimerions disposer d'un champ de recherche textuelle, pour trouver un ou des jeu(x) grâce à leurs noms.
Pour ce faire, nous ajoutons simplement un attribut search_fields à notre classe GameAdmin, qui représente un tuple de champs candidats pour la recherche textuelle :
class GameAdmin(admin.ModelAdmin):
list_display = ('name', 'release_date', )
search_fields = ('name', )
Mise en place de filtre
En plus de la recherche et du tri par colonnes, il est parfois intéressant de disposer de filtres sur les listes. Leur mise en place est tout aussi facile que le reste !
Définissons pour cela un attribut list_filter, qui représente un tuple de noms de champs candidats au filtrage :
class GameAdmin(admin.ModelAdmin):
list_display = ('name', 'release_date', )
search_fields = ('name', )
list_filter = ('types', )
Nous disposons désormais d'une administration tout à fait fonctionnelle.