Mission Secondaire - Support Django/Web

sascha salles project

Posted on Aug. 1, 2020, 10 a.m.

Présentation de la mission

Le département Hardware à mis en place une énorme base de données fonctionnant grâce à l'ORM (Object-Relational Mapping) de Django, cette base de données permet au service FPGA de gérer la charge de travail des employés, les boards, les FPGA, le laboratoire et une multitude de données supplémentaires. Il s'agit donc d'une base de données massive, aux requêtes complexes et aux rôles multiples.

Je m'efforcerai d'être le plus vaste possible concernant les informations de la base de données par mesure de sécurité.

Ma mission est de fournir un support au service FPGA/ASIC en leur apportant mon aide sur les outils Django. L'équipe étant une équipe d'ingénieurs hardware (matériel), la plupart savent développer en python (le langage le plus utilisé par la communauté scientifique) mais la majorité d'entre-eux ne possède que les bases. Ceci, explique l'utilisation de l'ORM Django permettant de se passer de la complexité d'SQL tout en utilisant de la simple POO en python. Une utilisation poussée de l'ORM permettrait à l'équipe un grand confort d'utilisation au quotidien. 

Les suggestions d'améliorations viennent souvent de Jean, formatteur Python et chef de la discipline FPGA & Asics dans la GBU AVS, mais aussi de Nicolas et Benjamin. 

Dans cet article, je vais traiter de trois problèmes/support que j'ai résolu dans le cadre de cette mission, les voici:

- Création d'un script de détection d'erreurs

- Gestion de multiples requêtes API.

- Aide à la création d'une nouvelle App dans l'ORM Django

sascha salles project

Présentation de l'ORM Django

Cher lecteur, je ne vous oublie pas, avant de rentrer dans les détails (que je me forcerai de vulgariser le plus possible), il me semble nécessaire de présenter ce qu'est l'ORM Django, et avant toute chose Django.

Django est un framework Web Python, tout comme il existe des frameworks Web PHP (Laravel, Symphony). Un framework est une boite à outils permettant au développeur de se simplifier grandement la vie en évitant de réecrire des tonnes de lignes de code. L'intéret secondaire mais nécessaire d'un framework est de se contraindre à une philosophie de code et de suivre les régles établies par le dit framework. Ces régles ont un but précis, permettre de maintenir facilement son code, et éviter de se répeter (le fameux DRY). Django est donc un framework Web permettant de créer des sites web en écrivant du code Python. Python étant un langage largement utilisé dans la communauté scientifique, très bien documenté et facile à apprendre, le service FPGA s'est décidé à l'utiliser.

Anectode : le site que vous consultez est programmé en Django et utilise l'ORM Django

L'ORM Django

Django embarque avec lui un ORM, sigle signifiant Object-Relational Mapping, qui permet de traduire du code Python en du code de base de données (voir photo ci-dessus). Il permet donc de se passer d'écrire du code en langage SQL (par exemple). L'ORM prend en charge plusieurs systemes de gestion de base de données (SGBD) tels que MySQL/MariaDB, PostgreSQL, MongoDB et bien d'autres.

L'autre avantage de l'ORM Django, et c'est là où toute la magie de Django opère face à d'autres frameworks, c'est la génération automatique d'une interface d'administration permettant des opérations de CRUD, sans écrire 1 seule ligne de Front. Le temps gagné est très important, et cela permet de pouvoir vraiment se concentrer sur le contenu et sur les requêtes que peux faire notre application.

 

1ère Mission - Création d'un script de detection d'erreurs

Problèmatique: Les ingénieurs de Thales doivent saisir des informations sur des projets auquels ils contribuent. Ces informations sont leurs dates de contribution à un projet. Un projet constitue une table dans la base de donnée, tout comme une personne en constitue une. Un projet à une date de départ et une date de fin, et une personne contribue à un projet d'une date A à une date B.

Le problème que Nicolas à relevé dans la base de données est que la date de fin de contribution à un projet d'une personne pouvait dépasser la date de fin d'un projet. Ce problème casse littéralement la base de données. Sachant que la saisie de contribution est déjà mise en place depuis longtemps, nous ne sommes pas à l'abris d'avoir beaucoup d'informations erronés. Nicolas m'a donc demandé de mettre fin au problème en incluant un test de validation dans le formulaire, mais aussi d'écrire un petit script python qui cherche dans les données et vérifie qu'elles sont cohérentes. De cette façon, il n'aura pas à controller toutes les valeurs à la main.

Ma solution

Le script que Nicolas voulait, doit dans le futur être compréhensible par le laboratoire en cas de reprise du code. Je me suis donc naturellement tourné vers Python une fois de plus. Le département Hardware utilise une version de Django spécifique nommée Django REST Framework, ce dernier sérialize les models et permet de transformer les données de la base en JSON. Cela ne diverge pas beaucoup par rapport à Django dans sa version normale, pour être plus précis, au lieu d'utiliser le pattern Model-View-Template(Custom) on utilise le pattern suivant Model-View-Serializer. 

Dans ce cas précis, cela m'est fortement utile, en effet grâce à ce détail je peux venir directement faire une requête API et comparer les valeurs de retour pour signaler l'erreur ou non.

Voici mon code :

import json

from urllib.request import urlopen

import datetime

addresses = ["serverthales1/","serverthales2/", "serverthales3/"]

def dateIncoherenceDetector(addresses):

    for url in addresses:

        request = urlopen(url)

        data = json.loads(request.read().decode(request.info().get_param('charset') or 'utf-8'))

            for item in data:

                if "endDate" in item:

                    project_end_str = item['endDate']

                    members = item['members']

                   if project_end_str != None and members != None:

                       for member in members:

                           member_end_str = member['endDate']

                           if member_end_str != None:

                               project_end_date = datetime.datetime.strptime(project_end_str,  '%Y-%m-%d')

                               member_end_date = datetime.datetime.strptime(member_end_str, '%Y-%m-%d')

                               if project_end_date < member_end_date:

                                   print('Erreur dans {0} --> {1} : {2} {3}'.format(url,  item['name'], member['firstName'], member['lastName']))

 

Cette solution est assez triviale et est facilement utilisable par n'importe quelle personne dans le service. Vous avez pu le remarquer j'ai utilisé le module Urlib pour faire mes requêtes. Sachant que l'erreur se répète dans plusieurs serveurs, j'ai ajouté les liens dans une liste puis j'ai bouclé dessus. En 20 minutes de code, cette solution permet d'éviter des heures de recherche dans la base de données.

2ème Mission - Gestion de multiples requêtes API

Problèmatique: Les ingénieurs de Thales gèrent leur documentation grâce à un wiki en intranet. La liste des propriétés intellectuelles (IP) et celle des BF (board functions) est gérée par la base de données Django, et pour obtenir l'une d'entre elles, il faut faire un GET avec l'API REST. Un des apprentis est venu me demander de l'aide pour concatener le resultat des deux requêtes afin d'obtenir une seule et unique liste contenant les IP et les BF. Plus tard on souhaitera l'afficher sous forme d'un tableau intelligent grâce au framework Front-End DataGrid de DevExpress, c'est d'ailleurs ce dernier qui se charge de faire le GET. Tout cela intégré au wiki. Précisons que dans la base de données, les tables IP et BF ont exactement les mêmes champs, il y a eu une mauvaise conception de la donnée par rapport aux besoins actuels, ma conception de l'idéal de cette gestion de donnée aurait été de rajouter un champs type en Foreign Key. L'apprenti en question étant qualifié en ingénierie électronique il ne disposait pas d'assez de temps pour régler le problème rapidement, Benjamin l'a donc dirigé vers moi. Une contrainte de temps fut de la partie, l'apprenti devait impérativement avoir le tableau intelligent qui fonctionne correctement le lendemain matin 10h.

Ma solution express

A cause de la contrainte de temps, mais surtout à cause d'une contrainte d'accès au serveur, j'ai décidé de concaténer les deux tableaux au-lieu de remodeler la base de donnée. La version de DataGrid qu'utilise les ingénieurs de Thales est basé sur des requêtes AJAX en jQuery, et la gestion de requêtes asynchrones s'avère fastidieuse d'une version à l'autre. J'ai résolu le problème en faisant un when, un systeme immitant les promises de JavaScript mais nettement moins puissant (en terme d'étendue du code). A partir de là, je concatène les données recueillies de chaque liste dans un tableau que je passe à DataGrid, ce dernier s'occupant de l'affichage. 

3ème Mission - Aide à la création d'une nouvelle App dans l'ORM Django

Problèmatique: Julie est une ingénieur FPGA coté AVS, et à besoin d'assistance dans la création d'une application supplémentaire au sein de l'ORM Django. L'outil qu'elle souhaite développer demande des requêtes complexes et une manipulation avancée de l'ORM Django. Cet outil à pour but une meilleure gestion de la sous-traitance et répond à de nombreux besoins. Voici un récapitulatif de ces besoins : 

partenaire2

Une partie de ces fonctionnalités seraient gérées par l'administration Django, mais les plus complexes et customisées seraient gérées par une interface web dédiée. Nous avons maquetté cette interface, d'abord sur papier, puis sur tableau en réunion. Une fois que nous avions correctement clarifié le besoin, nous avons aussi commencé à penser au schéma de données. Comme Django est très maléable nous avons directement commencé à coder.

La création d'une telle interface Web, poussée à son maximum à demandé plusieurs points et réunions, j'ai estimé la charge de travail à plusieurs mois et nous avons conclus au bout d'un certain temps, qu'il vallait mieux répartir le temps de mon stage sur la mission principale de Benjamin. Cette mission sera éventuellement répartie sur le temps d'une possible alternance actuellement en négociation avec le service.