Django : un framework Web pour les administrateurs Frédéric Saint-Marcel Service des Moyens Informatiques de l'inria Grenoble - Rhône-Alpes 655, avenue de l'europe - Inovallée Montbonnot - 38334 Saint Ismier Cedex France frederic.saintmarcel inria.fr Benjamin Ninassi Service des Moyens Informatiques de l'inria Grenoble - Rhône-Alpes 655, avenue de l'europe - Inovallée Montbonnot - 38334 Saint Ismier Cedex France benjamin.ninassi inria.fr Xavier Chopin Service des Moyens Informatiques de l'inria Grenoble - Rhône-Alpes 655, avenue de l'europe - Inovallée Montbonnot - 38334 Saint Ismier Cedex France xavier.chopin inria.fr Mots clefs Framework Web, Web2.0, Méta-Annuaire, ORM, MVC. 1 Introduction La tendance du World-Wide-Web est tournée vers le déploiement d'applications Web2.0. Dans le cadre de la refonte de notre système de gestion de comptes informatiques nous nous sommes intéressé aux outils et techniques Web2.0. Nous devions trouver des solutions adaptées à une équipe d'administrateurs système non spécialistes des architectures Web, qui devaient réaliser une application complexe. Nous avons décidé de nous appuyer sur un framework Web. Ayant déjà opté pour un développement spécifique basé sur des scripts écrit en Python et une base de donnée Mysql, cela nous a amené à choisir le framework Web python Django [1] pour les développements futurs. Il a été écrit par Adrian Holovaty et Simon Willison avec comme slogan «le framework Web pour les perfectionnistes avec des délais à tenir». Il est publié selon les termes de la license BSD et possède une communauté active et dynamique. L'architecture du nouveau système est basée sur un «méta-annuaire». Couche logicielle venant se greff er au-dessus des applications et des annuaires, il permet d avoir une vue unifiée de l ensemble des données d une entreprise. Il assure aussi la synchronisation des identités informatiques entre un référentiel unique et les ressources existantes qui constituent le système d information. 1
2 Le référentiel des identités informatiques Il contient la totalité des attributs des identités à synchroniser avec par exemple l'utilisation d'un annuaire de type LDAP ou d'un système de base de données. L'alimentation du référentiel est la plupart du temps réalisé par des scripts et/ou le développement d'une interface graphique dans un langage donné. On utilise pour cela des librairies proposés par les langages pour effectuer les opérations sur le référentiel (ex : pyhton perl-ldap, php-mysql, Java-JDBC). Les éléments d'architecture et d'organisation du code ne sont pas fourni et sont à la charge des développeurs. Le framework Django facilite cette tache en utilisant le paradigme MVC (Model View Controler) [2] comme architecture et modèle de conception pour l'interface homme-machine. Cela assure une séparation entre un modèle (modèles de données), une vue (interface utilisateur) et un contrôleur (logique de contrôle, gestion des évènements). Il fournit aussi un ensemble de bibliothèques, d'outils et de conventions pour le développement d'applications Web. On peut citer à titre d'exemple des modules pour la gestion de l'authentification et des permissions, l'internationalisation, la syndication (RSS), l'envoi d'emails. 2.1 Le modèle de données Le premier travail consiste à définir le modèle de données du référentiel. Pour cela nous avons écrit des classes python qui décrivent les tables de la base de donnée. Une instance de la classe du modèle correspond à un enregistrement de la table. A titre d'exemple, le schéma 1. comporte la traduction du modèle conceptuel Merise [3] d'une relation entre un utilisateur et un groupe d'utilisateurs vers le modèle de données Django correspondant. 1,1 Primary Group 0,n User Name Firstname Email CreationDate ClosureDate... Group Name Gid... 0,n Secondary Group 0,n class Group(models.Model): idgroup = models.autofield( primary_key=true) name = models.charfield( unique=true, max_length=50) gid = models.positiveintegerfield( unique=true)... class User(models.Model): iduser = models.autofield( primary_key=true) name = models.charfield( max_length=50) firstname = models.charfield( max_length=50) email = models.emailfield( blank=true, unique=true) creationdate = models.datefield( default= datetime.datetime.now()) closuredate = models.datefield(, default= datetime.date(2099, 1, 1)) primarygroup = models.foreignkey(group, db_column='gid', blank=true) secondarygroup = models.manytomanyfield(group, through='secondarygroup')... class SecondaryGroup(models.Model): idsecondarygroup = models.autofield(primary_key=true) idgroup = models.foreignkey(group, db_column='idgroup') iduser = models.foreignkey(user, db_column='iduser') Figure1 - Modèle de données Django. On retrouve pour chaque entité une classe avec la déclaration des champs et les 2
informations suivantes : le type de la donnée dans la base de donnée (ex : Charfield = VARCHAR, DateField = DATE) les contraintes d'intégrité (ex : l'unicité du champ) les relations entre les entités et leur cardinalité. Ainsi la relation de cardinalité [0,n] pour les groupes secondaires d'un utilisateur correspond au champ «ManyToManyField». On voit par ailleurs que cette relation est traitée par une table intermédiaire avec la classe «SecondaryGroup». 2.2 Vers le modèle objet Le framework s'appuie sur des opérations de haut niveau pour la gestion des données avec la technique d'orm (Object Relational Mapping) [4]. Elle permet de faire une translation du modèle relationnel d'une base de donnée vers un modèle objet et de réduire considérablement le nombre de lignes de code. Les développeurs manipulent des objets avec des opérations qui sont automatiquement transformées en requête SQL par l'orm avec l'utilisation d'une API python basé sur le modèle CRUD (Create Read Update Delete) [5] pour la persistance des données. Dans l'exemple ci-dessous «users» contient la liste de toutes les instances de la classe «User» avec la génération du code SQL correspondante: users = User.ojbects.all() ORM SELECT`User.`idUser`,`User`.`firstname`,`User`.`name`,`User`.`email`,`User`.`creationDate`, `User`.`closureDate`, `User`.`login`, `User`.`gid`, FROM `User` 2.3 La conception de l'ihm Le deuxième travail consiste à réaliser l'interface utilisateur pour manipuler les données. Django se distingue des autres framework par la mise à disposition automatique d'une interface web d'administration des données. Elle fournit une vue ergonomique et fonctionnelle qui permet de s'affranchir des étapes de conception graphique. La devise du framework est de minimiser au maximum le développement de code et d'utiliser la philosophie DRY («Don't Repeat Yourself») [6]. Pour cela il suffit de déclarer les classes du modèle qui vont être utilisées dans l'interface d'administration. Elle est entièrement paramétrable avec les exemples de fonctionnalités suivants : interface de visualisation des données moteur de recherche gestion des formulaires (ajout, modification, suppression) gestion de l'organisation et de l'affichage des champs de formulaires 3
possibilité de création de «widget» HTML pour les champs de formulaires La figure 2. montre le résultat du formulaire d'ajout d'un utilisateur dans l'interface d'administration. Django intègre par défaut des mécanismes de validation pour la saisie des champs de formulaire (ex : vérification du format sur un champ «EmailField») et il est possible d'écrire ses propres validations sur des champs métiers avec les méthode «clean_». class UserAdmin(admin.ModelAdmin): form = UserAdminForm inlines = [SecondaryGroupInLine]... class UserAdminForm(forms.ModelForm) class Meta: model = User def clean(self): cleaned_data = self.cleaned_data creationdate = cleaned_data.get('creationdate') closuredate = cleaned_data.get('closuredate') if (closuredate <= creationdate): raise forms.validationerror("veuillez entrer une date de fermeture postérieure à la date de creation.") Figure 2 - Interface d'administration Django Le mécanisme «inlines» permet d'éditer un modèle dans la même page qu'un modèle parent. Ainsi les groupes secondaires sont éditables dans le formulaire d'un utilisateur. Il est possible de créer facilement des vues pour l'affichage des données (liste des comptes informatiques, comptes-rendu) sous différents formats : HTML, PDF, feuille Excel. Django fournit un système de modèle HTML évolué (ex : gestion de la pagination) avec des attributs et des filtres pour extraire les données. Django propose aussi un module pour développer rapidement des formulaires Web. Une des applications a été de fournir une interface Web pour la centralisation du changement des mots de passe des utilisateurs. 3 Synchronisation des identités Après la gestion du référentiel, nous avons développé la brique logicielle de synchronisation du référentiel avec les ressources informatiques (ex : annuaire LDAP) On retrouve principalement deux techniques : la méthode «Push» et «Pull». Nous avons choisi la première avec l'utilisation d'un moteur de synchronisation dit «intelligent» qui s'occupera de lancer des sous-connecteurs en charge d'écrire dans les différentes 4
ressources informatiques. Cette méthode présente plusieurs avantages : centraliser et homogénéiser les développements des sous-connecteurs utilisation de l'orm du framework pour la synchronisation avec le référentiel simplification des briques logicielle de gestion des erreurs et de notifications. possibilité de lancer le moteur pour l'initialisation ou la reconstruction automatique d'une ressource informatique (ex : annuaire LDAP avec une base corrompue) Interface d'administration Formulaire (chgt. de mot de passe) Vue utilisateur (liste des comptes informatiques) ORM Référentiel (SGBD Mysql) Framework Django Moteur de synchronisation Sous-connecteurs : + OpenLDAP + Active Directory + Boîte/Alias Mail (Cyrus-Imap) + gestionnaire de liste (Sympa) + Espace de données personnel Figure 3 - Architecture du méta-annuaire Les sous-connecteurs ont été développés sous forme de librairies ré-utilisables. On peut citer à titre d'exemple, l'alimentation d'un annuaire OpenLDAP avec un schéma POSIX et d'un annuaire Windows Active Directory. Le moteur de synchronisation exploite l'orm de Django avec l'api «queryset» qui permet de faire des requêtes d'extraction SQL très rapidement. L'exemple ci-dessous permet de trouver tous les utilisateurs du référentiel qui ont une date de fermeture de leur compte informatique égale à la date du jour. user = User.objects.filter(closureDate=datetime.now()) Le moteur de synchronisation est aussi basé sur deux automates qui permettent de 5
respecter des règles de gestion. Un premier automate d'état permet de le renseigner le moteur sur l'état des données (ex: état = [ajout, modification, suppression, valide, en attente]) Le deuxième automate permet de lancer les sous-connecteurs dans un contexte donné (ex: un utilisateur en fonction de ces habilitations sera inscrit dans des ressources informatiques différentes) La brique logicielle de gestion des erreurs utilise une table métier de la base de données pour stocker les résultats d'exécution des sous-connecteurs. Cela permet au moteur de synchronisation de notifier par courriel et de rejouer les sous-connecteurs en erreur (ex : annuaire LDAP hors-service). On dispose aussi dans l'interface d'administration d'un tableau de bord d'exécution des sous-connecteurs. 4 Conclusion Nous gérons actuellement une base de compte informatique de près de sept-cent utilisateurs avec un taux de renouvellement de trente pour-cent par an. La gestion des comptes informatiques évolue pour intégrer de nouveaux besoins : ajout d'attributs pour les identités, connexion vers de nouvelles applications. Il est donc important de s'appuyer sur des briques logicielles modulaire qui permettent de répondre rapidement aux évolutions. Le framework Django fournit cette base solide d'architecture. Cette solution de «méta-annuaire» se veut facilement ré-utilisable et extensible pour d'autres instituts ou laboratoires en un minimum de temps. En effet nous avons pu expérimenter en comparaison de l'ancienne solution la rapidité du développement, la prise en main rapide et la génération optimum de code avec l'utilisation du framework. Nous travaillons actuellement sur deux perspectives : un moteur de vérification de cohérences entre le référentiel et les ressources informatiques. ouvrir le périmètre fonctionnel de l'outil pour développer rapidement des briques logicielles d'administration système. Bibliographie [1] http://www.djangoproject.com/ [2] Burbeck, S. (1987, 1992). Applications Programming in Smalltalk-80 : How to use Model-View-Controller (MVC). http://st-www.cs.uiuc.edu/users/smarch/stdocs/mvc.html. [3] H. Tardieu, H. Rochfeld, A. Colletti, R. (1991). La méthode Merise, Tome 1 : Principes et outils. Éditions d'organisation. [4] Ambler S.C. (2007). Agile Database Techniques. John Wiley & Sons. [5] Kilov, H. (1998). Business Specifications: The Key to Successful Software Engineering. Prentice Hall. [6] Andrew Hunt, A. Thomas, D. (1999). The Pragmatic Programmer, Addison-Wesley. 6