TD1 Etudiants - Découverte de la programmation d'un module sous Odoo v14
Machine virtuelle: VM
OS : Linux Ubuntu 64 bits
Mode Attachement multiple
RAM : 8 Go minimum.
3 ou 4 processeurs (Onglet « Système » puis « Processeur »).
Mémoire vidéo : 128 Mo. Activer l’accélération 3D.
Activer le presse-papier partagé.
Pour modifier la résolution d’affichage de la VM :


Mot de passe root Linux: matskipwd Informations de connexion à Odoo : admin : admin
Objectifs
Ce TD a pour objectif de comprendre le framework de développement interne à Odoo et de le mettre en application dans le cadre de la création d’un module simple. Plus précisément, la création du module va suivre les étapes suivantes :
Définition des objets Python assurant la persistance des données en base
Création des interfaces utilisant ces objets
Création d’une traduction française du module (internationalisation)
Importation de données de base
Ce TD ne requiert pas de compétence de développement en Python.
1. Test de l'environnement
Lancer PyCharm . Ne pas mettre à jour PyCharm s’il vous le propose.
Un projet « Odoo » a été créé. Il a été configuré pour pouvoir créer directement un nouveau module en utilisant les bibliothèques Odoo 14.
Le dossier local-src quicontiendra le module créé est directement accessible de l’éditeur: 
Changer le nom de votre base de données dans le fichier docker-compose.yml: 
Lancer le projet Python en passant par le terminal directement depuis PyCharm:
docker compose run --rm -p 8014:8069 odoo odoo --workers=0
Odoo sera lancé avec une base de données identifiée par votre nom.
Odoo est maintenant accessible ici : http://localhost:8014/. Vous pouvez utiliser l'email : admin et le mot de passe : admin
Arrêter ensuite le projet: Ctrl + C dans le terminal
2. Principe
Odoo est basé sur une architecture MVC :
Couche Modèle: définit la structure des données
Couche Vue: décrit l’interface utilisateur
Couche Contrôleur: est en charge de la mise en œuvre de l’ensemble des règles de gestion et de la logique applicative
Ces 3 couches sont développées et maintenues sous forme de modules indépendants.
La couche Modèle est définie avec des objets écrits en langage Python, dont les données sont stockées dans une base PostgreSQL. Le mapping Objet -> Base de données relationnelle est automatiquement géré par Odoo via un mécanisme d’ORM (Object Relational Mapping).

Le lien entre la couche C et la couche V est géré par le protocole XML-RPC et/ou NET-RPC.
3. Structure d'un module
Principes
Les modules utilisent l’ORM (Object-Relational Mapping) d’Odoo pour rendre persistantes leurs données dans une base de données relationnelle (PostgreSQL). Les données peuvent être insérées en utilisant le module (saisie manuelle) ou lors de l’installation de celui-ci en utilisant des fichiers XML ou CSV contenant les données à importer.
Les modules de base d'odoo sont localisés dans le dossier odoo/src/addons. Les nouveaux modules doivent êtres créés dans le dossier odoo/local-src. Les modules externes/communautaires seront à placer dans le dossier odoo/external-src.
Un module Odoo doit respecter les conditions suivantes :
3 fichiers Python sont obligatoires:
__init__.py: fichier d’initialisation du module (ATTENTION aux 2 underscores en début et en fin de nom de fichier !)__manifest__.py: fichier de description du module (ATTENTION aux 2 underscores en début et en fin de nom de fichier !)Au moins 1 fichier de code Python (classes) contenant des objets (modèle)
Les vues (formulaires, listes, ...), les menus et les actions (clics sur un bouton, etc.) sont définies dans un ou plusieurs fichiers XML.
Il est possible d’ajouter des données lors de l’installation du module (contenues dans des fichiers XML ou CSV).
Il est possible de créer des rapports et/ou des Wizard (assistants).
Il est possible de gérer des traductions du module en différentes langues.
Il est possible de décomposer le code Python ou XML produit en plusieurs fichiers répartis dans des dossiers différents.
L’encodage des fichiers doit être au format UTF8.
Fichier __init__.py:
Fichier d’initialisation du module, exécuté́ au début du programme.
Importe les modules Python (import…) qui doivent être chargés en mémoire.
Fichier __manifest__.py:
Fichier de description du module
Spécifie les fichiers XML qui seront parsés lors de l'initialisation du serveur
Spécifie les dépendances du module
Doit intégrer un dictionnaire Python contenant les clés suivantes :
Clé | Description |
|---|---|
name | Nom du module |
version | Version du module codée sur deux chiffres (ex. 1.1 ou 2.3) |
author | Auteur du module |
description | Partie à renseigner la plus importante. Description longue du module, y compris la documentation sur l'utilisation du module. |
depends | Liste des modules dont dépend le module développé. Suppose que le développeur hérite d’un module existant et ajoute/modifie des fonctionnalités. Si aucune dépendance spécifique n'est requise, indiquer simplement ['base']. |
website | Site Web du module. |
category | Catégorie dans laquelle le module va être placé. |
images | Images du module. |
data | Contient : Les fichiers de vues (.xml), les fichiers de données de base (.xml ou .csv) et les fichiers de sécurité (.xml) |
demo | Contient la liste des fichiers de démonstration. |
installable | Indique si le module est installable ou non. Valeur : |
auto_install | Installation automatique du module. |
application | Booléen ( |
license | Licence du module : AGPL-3, LGPL-3, OPL-1 (Odoo Proprietary License v1.0), etc. (LGPL-3 par défaut.) |
css, maintainer, external dependencies, ... (Cf. https://www.odoo.com/documentation/14.0/reference/module.html) |
Exercice 1: Création d'un premier module (vide)
Créer un nouveau dossier students dans le dossier local-src
Créer un sous-dossier models, qui contiendra les classes Python représentant les données (modèle) de l’application.
Remarque : Git étant installé dans la VM, vous pourrez au fur et à mesure valider l’ajout de chaque fichier au projet Git.
Dans le dossier models, créer les fichiers Python suivants:
__init__.py:from . import studentsstudents.py(vide pour le moment)
Dans le dossier students (racine du module), créer les fichiers Python suivants:
__init__.py:from . import models__manifest__.py:{ "name": "Gestion des étudiants", "version": "0.1", "category": "Generic Modules/Others", "description": """Test création module gestion des étudiants Odoo v14""", "author": "Moi", "depends": ["base"], "installable": True, "auto_install": False, }
Enregistrer (menu File > Save All). Structure de fichiers obtenue : 
Lancer le serveur.
Remarque : à la création de la base, on peut notamment voir dans la console de PyCharm les modules et leurs données qu’Odoo installe :
Connectez-vous avec les identifiants : admin / admin. Remarque : En mode developpement le mot de passe est identique au nom d'utilisateur.
Notre module est bien disponible à l’installation (supprimer le filtre sur « Application »). NE PAS INSTALLER LE MODULE POUR L’INSTANT.
Cliquer sur le bouton « Info sur le module » pour visualiser sa description: 
Nous ne voyons que sa description, mais ni sa version, son nom technique, etc. Pour cela, nous allons activer le mode développeur. Il suffit de rajouter ?debug=true juste après web dans l’URL. 
Nous pouvons maintenant visualiser toutes les informations techniques nécessaires. 
On remarque le numéro de version du module.
Le module développé nécessite le module base, représentant le noyau d’Odoo. 
Arrêter le projet.
3. Codage des objets
Principes
Le module à développer permet de gérer (partiellement) des diplômes (ou formations) et des étudiants.
Nous allons écrire le code du fichier students.py. Ce fichier va notamment contenir les objets métiers de la couche model représentant les données qui seront stockées dans la base de données. Les objets métiers sont déclarés comme des classes Python étendant la classe models.Model, classe qui assure la persistance automatique des données via l’ORM.
Pour définir un nouvel objet, il faut définir une nouvelle classe Python. Cette classe doit hériter de la classe Model du module models fourni par Odoo. La syntaxe est la suivante:
Un seul attribut de classe est obligatoire : _name. Les autres sont optionnels. Il est tout de même recommandé d'indiquer aussi _description. Vous pouvez retrouver tous les attributes ici : https://www.odoo.com/documentation/14.0/reference/orm.html#model-reference
Attribut | Description |
|---|---|
_name | Nom formel de l'objet |
_description | Nom informel de l'object |
_inherit | La classe hérite d’une autre classe |
_table | Nom de la table SQL. Par défaut c’est la valeur du champ _name, les points (.) étant remplacés par des underscores (_) |
_sql_constraints | Contraintes SQL : par exemple, contrainte de domaine, contrainte d’unicité, etc. Il est préférable d’utiliser |
_order, _rec_name, ... |
Types d'attributs: Types simples
Pour chaque attribut (colonne) de l’objet, il est nécessaire de définir un nom et le type de données. Principaux types simples :
Type | Définition |
|---|---|
Booléen |
|
Entier |
|
Décimal |
|
Texte |
|
^ |
|
HTML |
|
Date (seule) |
|
Date et heure) |
|
Données binaires (photo, etc.) |
|
Liste déroulante (valeurs fixes) |
|
Exemples de paramètres optionnels fréquents :
required=True(champ obligatoire)readonly=True(champ en lecture seule)default=valeur(valeur par défaut). Par exemple : True pour un booléen, val3 pour une liste déroulante, etc.)index=True(pour indexer un champ de recherche),help="indication d’aide"(pour fournir une bulle d’aide lors du passage sur le champ avec la souris, etc)
Pour utiliser ces types d’attributs, il est nécessaire d’importer le module fields.
Remarque : Pour plus de détails, cf. https://www.odoo.com/documentation/14.0 et http://odoo-new-api-guide-line.readthedocs.io/en/latest/index.html
Exercice 2:
La langue de base d’Odoo étant l’anglais, il est préférable de créer les noms des champs, ainsi que les descriptions en anglais.
Ajouter le code suivant dans le fichier students.py Attention à bien respecter l’indentation !!!!
Remarques:
Le nom de la classe respecte le CamelCase.
Le module
modelsdont nous utilisons la classeModeln’a rien à voir avec le dossiermodelsque nous avons créé. Le nom de ce dossier respecte les conventions de nommage d’Odoo, mais nous aurions pu le nommermodel.
Cet objet permet de gérer une liste d’étudiants avec leur diplôme :
number: correspond au numéro INE (numéro d’identification national des étudiants) codé sur 10 chiffres et 1 caractère (d’où unfields.Char(size=11)).firstname: prénom de l’étudiantlastname: nom de l’étudianttraining: diplôme
Ici, nous avons décidé de préfixer le nom de la classe (attribut _name) par students (nom du module) afin de retrouver plus facilement les tables qui seront générées dans PostgreSQL (ce fonctionnement est recommandé par Odoo) : "students." sera remplacé par "students_" dans le nom de la table.
Enregistrer (menu File > Save All).
Lancer le projet. Et mettre à jour le module.
Si vous avez une erreur à la mise à jour ou à l’installation du module, désinstaller le module (ou annuler l’installation), fermer Odoo et arrêter le projet Python. Relancer le projet et installer le module. Si vous avez toujours une erreur, cela provient de votre code… Dans ce cas, bien regarder la ligne en erreur qui se trouve toujours à la fin de la pile d’exécution (descendre avec l’ascenseur jusqu’en bas)
On remarque que des champs supplémentaires (nécessaires à Odoo) ont été ajoutés, ainsi que des contraintes d’intégrité. L’attribut id qualifie de manière unique un enregistrement (primary key) dans un modèle spécifique ; Odoo gère donc lui-même les identifiants. Les champs create_uid et write_uid permettent de déterminer quel utilisateur a créé / modifié en dernier un enregistrement. Idem pour les dates de création (create_date) et de dernière modification (write_date) de l’enregistrement. 
Dans Odoo, menu APPLICATIONS, désinstaller le module students. Arrêter le serveur.
Types d'attributs : Types relationnels
Pour pouvoir gérer les associations entre les classes et ainsi les relations entre les tables, des types relationnels ont été ajoutés.
Type | Définition |
|---|---|
Many2one |
|
One2many |
|
Many2many |
|
Les parametres optionnels sont les mêmes que pour les types simples.
Exercice 3:
Remplacer tout le code par le suivant dans le fichier students.py:
Explications:
Nous gérons 2 objets différents : Etudiant et Diplôme (Formation). Les 2 sont reliés via des attributs de type relationnel.

Le champ
training_idde l’objet nomméstudents.studentest lié à l’ID de l’objet nomméstudents.training(clé étrangère dans la table). Ce code va générer une liste déroulante permettant de sélectionner un diplôme. Remarque : il est aussi possible d’avoir une liste déroulante liée à un autre objet (classe) d’un autre module (Cf. TD suivant).Le champ
student_idsde l’objet nomméstudents.trainingest lié au champtraining_idde l’objetstudents.student. Il permettra à partir d’un diplôme d’avoir accès à la liste des étudiants (sous la forme d’untreeintégré dans le formulaire). Cette liste est nommée Training students.Il est toujours nécessaire de créer les associations dans les 2 sens : dans notre cas One2many pour une relation et Many2one pour la seconde:
Relation One2many dans
students.training: à un diplôme correspondent plusieurs étudiants (objetsstudents.student).Relation Many2one dans
students.student: les étudiants ne sont inscrits qu’à un seul diplôme (objetstudents.training) au maximum.
Enregistrer (menu File > Save All). Lancer le serveur et installer le module.
3. Création de l'interface
Principes
La création d’une interface d’un module consiste à créer les menus, vues, actions, rôles, droits d'accès, etc. Sous Odoo, les interfaces sont créées et configurées dans des fichiers XML.
Le fichier contenant la définition de l’interface doit être référencé dans l’attribut data du fichier __manifest__.py. Ainsi, si le fichier module_views.xml contient la description de l’interface du module, il est nécessaire d’ajouter la ligne "data": ["module_views.xml"] dans le dictionnaire Python.
Structure du fichier XML de l’interface :
Vous pouvez retrouver la documentation complète ici : https://www.odoo.com/documentation/14.0/developer/reference/addons/data.html
Menus
Syntaxe des menus:
Le module est déclaré comme suit :
<menuitem id="idModule" name="Nom du module" />C’est ce nom que l’on retrouvera dans le menu général.Menu de 1er niveau (non cliquable) :
<menuitem id="idMenu1" parent="idModule" name="Nom du 1er menu de niveau 1 dans la barre de menu" />Menu de 1er niveau (cliquable) :<menuitem id="idMenu2" parent="idModule" name="Nom du 2ème menu de niveau 1 dans la barre de menu" action="[ACTION_ID]"/>Menu de 2ᵉ niveau (cliquable) :
<menuitem id="idSousMenu1" parent="idMenu1" name="Nom du menu de niveau 2 sous le 1er menu dans la barre de menu" action="[ACTION_ID]"/>Oùactionest l’évènement déclenché après le clic sur le menu. Il est nécessaire de définir une action à exécuter (nous y reviendrons plus loin).
Exercice 4
Ajouter la ligne "data": ["views/students_views.xml"] dans le __manifest__.py
Créer le fichier students_views.xml dans le dossier views à la racine du module students
Ce fichier contiendra la hiérarchie suivante en respectant la syntaxe des menus précédents (à intégrer dans la balise <odoo>) et sans l’attribut action pour le moment :
Menu principal du module : Students
Menus de 1er niveau (cliquables) :
Trainings
Students
Aider vous des informations précédentes et de la documentation Odoo pour créer ces menus
Mettre à jour le module.
Pour vérifier les menus créés et si ceux-ci sont conformes, cliquer sur l’onglet « Fonctionnalités installées », rubrique « Menus créés » du module. 
Actions
= Évènement déclenché suite à un clic sur une vue ou un menu par exemple.
Pour déclarer une action, il faut utiliser le modèle
ir.actions.act_windowSyntaxe :
<record model="ir.actions.act_window" id="actionID"> <field name="name">NomAction</field> <field name="type">ir.actions.act_window</field> <field name="res_model">Objet</field> <field name="view_mode">tree,form</field> </record>Où:
model: : type d’élément. Ici, c’est une action doncir.actions.act_windowid: identifiant de l’action (unique)name: le nom de l’action (obligatoire)type: toujoursir.actions.act_window(non obligatoire)res_model: le modèle (objet) Python sur lequel pointe l’action (obligatoire)view_mode: liste des vues autorisées. Attention, à toujours respecter l’ordre tree,form, car quand on clique sur le menu c’est la vue tree qui est affichée. ATTENTION, l’id et le name (valeur de<field name="name">) doivent être uniques (pas de doublon possible).
Exemple: création d’une action de clic sur le menu « Students ». Ici, la vue par défaut sera la vue
tree.<record model="ir.actions.act_window" id="action_students_view_tree"> <field name="name">Students</field> <field name="type">ir.actions.act_window</field> <field name="res_model">students.student</field> <field name="view_mode">tree,form</field> </record>
Modifier la ligne du menu (Cf. Exo 4) pour indiquer l'action à exécuter: <menuitem id="students" name="Students" parent="mainMenu" action="action_students_view_tree"/>
Vues
Vue (View) :
= Moyen pour afficher les objets sur le navigateur web du client.
Plusieurs types de vues peuvent être déclarés pour le même objet et peuvent être utilisés suivant leur priorité
Types de vues possibles :
form (Formulaire). Permet la visualisation, l’insertion et la modification d’un unique objet (enregistrement de la base de données). Tous les champs de l’objet sont généralement affichés.
tree (liste). Permet de visualiser plusieurs objets (enregistrements). En général, une partie seulement des champs est affichée.
graph
kanban
calendar
gantt
Pour déclarer une vue il faut utiliser le modèle ir.ui.view. Syntaxe :
<record model="ir.ui.view" id="viewID"> <field name="name">nomObjet.TypeVue</field> <field name="model">Objet</field> <field name="type">form</field> <field name="arch" type="xml"> <!--contenu de la vue: <form>, <tree>, <graph>, ... --> </field> </record>Où:
model: : type d’élément. Ici, c’est une vue doncir.ui.viewid: identifiant de la vue (unique)name: règle de nommage :nomObjet.TypeVue. Exemple :students.formtype: type de vue (par défautform). Balise non obligatoire siform.arch: l’architecture de la vue et qui est de type XML ATTENTION, l’id et le name (valeur de<field name="name">) doivent être uniques (pas de doublon possible).
Contenu d'une vue formulaire:
Où:
form: vue de type formulairefield: pour déclarer chaque champ de l’objet lié à la vue formulaire
Attributs d’une vue formulaire (form) :
Attributs communs:
string: étiquette de l’élémentnolabel: 1 (ou True) pour masquer l’élémentcolspan: Nombre de colonnes sur lesquelles le champ doit s’étendrerowspan: Nombre de lignes sur lesquelles le champ doit s’étendrecol: Nombre de colonnes à allouer à ses éléments enfantsinvisible: 1 (ou True) pour cacher complètement l’élément...
Attributs des champs (
field):required: 1 (ou True) => un champ obligatoirereadonly: 1 (ou True) => champ en lecture seulpassword: 1 (ou True)...
Attributs des labels (
label) :for: pour indiquer le nom du champ (field) lié...
Attributs des boutons :
type: type du bouton : workflow (par défaut), objet ou actionname: signal workflow, nom d’une fonction (sans parenthèse) ou action à appeler (dépendant du type)confirm: message de confirmation si cliquéstates: liste d’états d’affichage du bouton, utilisant un séparateur comma (,)
Plus de détails ici : https://www.odoo.com/documentation/14.0/reference/views.html
Contenu d'une vue liste ou arbre (tree):
Exemple :
<field name="arch" type="xml"> <tree string="Student" > <field name="number"/> <field name="firstname"/> <field name="lastname"/> </tree> </field>
Exercice 5
Remplacer le contenu XML du fichier students_views.xml par celui-ci :
Sauvegarder.
Mettre à jour le module.
On ne retrouve pas le module dans le menu général. En réalité, il est bien disponible, mais n’est pas accessible pour des questions de droits que nous réglerons ultérieurement. 
Dans les outils du développeur, cliquer sur Devenez un super-utilisateur. 
Nous avons maintenant accès au module. 
On remarque que c’est bien la vue tree (liste) qui est affichée par défaut.
Créer 2 étudiants. Recliquer sur le menu. 
Dans cette vue, nous avons restreint l’affichage à 2 champs.
Remarque : le design de la fenêtre affichant les enregistrements saisis suite à la sauvegarde n’est pas très esthétique, mais il suffira de modifier la mise en forme, ce que nous ferons ultérieurement.
Exercice 6: Création de l'interface pour les diplomes
Faire de même pour les diplômes
Remarque : il est possible de créer les vues dans plusieurs fichiers XML (un pour les vues de Student, un pour les vues de Training) ou de les intégrer dans le même fichier XML. Dans le premier cas, il faut penser à modifier la clé "data" du fichier __manifest__.py. ATTENTION également à ne pas dupliquer les menus (qui doivent se trouver dans un seul fichier XML).
Mettre à jour le module.
Vues créées : 

Vue form avancé
Il existe plusieurs tags pour améliorer l'interface une vue form.
Tag | Définition |
|---|---|
| Faire un encadré dans la fenetre principal (vivement recommandé) |
| Faire des regroupements, permet d'afficher le label sans indiquer le tag |
| Affiche des onglets |
| Indiqué à l'interieur d'un |
L'attribut name n'est pas obligatoire mais il est préferable de le renseigner pour permettre un heritage plus aisé de la vue, nous verrons cela ultérieurement
Exercice 7: Amélioration de l'interface et de de l'interaction Diplômes <> Etudiants
Remplacer la vue form des training par:
Faire la vue student de cette manière :

Mettre à jour le module.
Cration d'un diplome et d'un étudiant: 
Cliquer sur « Ajouter une ligne » de l’onglet « Students » et ajouter un étudiant sans diplôme (formation) : 
Sauvegarder et Fermer. Sauvegarder la formation. Par défaut, c’est la formation actuelle qui est renseignée.
On peut aussi permettre l'ajout d'un student depuis un training en mode "en-ligne".
Remplacer le <field name="student_ids" /> dans la vue form training par :
L'attribut editable="bottom" permet d'ajouter une ligne a la suite dans le tableau, on pourra remplacer bottom par top pour ajouter une ligne en premiere position.
Ajouter un nouvel étudiant à un diplôme. 
Cliquer sur le menu "Students" et créer un étudiant appartenant à un diplôme. 
On remarque que le nom du diplôme est automatiquement affiché dans une liste déroulante quel que soit le formulaire. Par défaut, quand un champ name est défini dans l’objet, celui-ci est utilisé comme valeur à afficher dans la liste déroulante, sinon ce sera l’ ID et donc par exemple quelque chose du genre students.training,1, students.training,2, etc.
Pour afficher le code et non le libellé, il est nécessaire de modifier le fichier students.py de la façon suivante :
_rec_name sert à préciser quel champ d'une relation Many2one, est à afficher.
Relancer le serveur. 

Internationalisation
Principes
Nous allons créer un fichier d’internationalisation permettant d’ajouter la traduction française du module. Chaque module peut fournir plusieurs traductions pour adapter l’interface aux préférences de l’utilisateur, notamment à la langue choisie.
Les traductions doivent être créées dans un dossier nommé i18n. Chaque traduction est stockée dans un fichier LANG.po, LANG correspondant au code local de la langue.
Exercice 8
Chaque module dispose par défaut d’un modèle de traduction qu’il est possible de télécharger à partir d’Odoo et à partir duquel on peut créer des traductions. Pour cela, dans le module CONFIGURATION, menu Traductions > Import/export, cliquer sur Exporter une traduction. Paramètres de l’export :

Cliquer sur « Exporter ». Télécharger le fichier .pot en cliquant sur le lien web.

Créer un dossier i18n à la racine du module. Déplacer le fichier .pot obtenu dans ce dossier.
Nous allons utiliser l'outil POEdit pour créer les traductions. Ouvrer Poedit. Cliquer sur File > New from POT/PO file et selectionner le fichier students.pot. Indiquer French dans Language of the translation et cliquer sur OK
Mettre à jour le module (pas besoin de le désinstaller/réinstaller). Comme la langue par défaut choisie lors de la création de la base de données était le français, l’interface affiche la traduction que nous venons de créer. Vous pouvez désormais traduire les termes. 
Une fois cela fait vous pouvez sauvegarder dans le dossier i18n en cliquant sur Save. Attention de bien nommer le fichier fr.po
Ouvrer le fichier fr.po dans Pycharm. Une traduction est construit de cette manière :
La premiere ligne
#. module: studentsindique le module auquel appartient la traudctionLes lignes suivantes indiquent de quels modèles viennent la traduction
msgid "Last Updated on"est la valeur source.msgstr "Dernière modification le"est la traduction
Pour modifier un fichier .po, vous pouvez ouvrir le fichier fr.po avec Poedit et efiter les infos. Nous verrons dans l'exercice 10 comment mettre à jour un fichier .po après l'ajout de nouveaux champs dans le code source.
Si vous modifiez par la suite la traduction d’un champ dans le fichier .po alors que le module a déjà été installé précédemment, la traduction ne sera pas modifiée. Il est nécessaire de recharger la traduction en cochant la case « Remplacer les termes existants » dans le module CONFIGURATION.
Remarque : lors de l’installation d’un module, les traductions sont importées et stockées dans une table locale à la base de données (ir_translation) puisqu’il est ensuite possible d’amender la traduction propre à une base de données (Cf. TDA - Administration du cas MATSKI). La désinstallation du module ne supprime pas les traductions stockées dans la table ir_translation. C’est pour cela qu’il faut remettre à jour la traduction si vous modifiez le fichier po. Cf. remarque en rouge en page précédente.
Désinstaller le module afin de le vider de ses données.
Importation de données
Principes
Des données peuvent être importées lors de l’installation du module. Ces enregistrements peuvent être importés dans tous les cas (données de base) ou seulement si la base de données a été́ créée avec l'option « Charger les données de démonstration » (dans ce cas, elles sont appelées données de démonstration). Il est possible de charger des données en utilisant des fichiers d’import au format XML ou CSV. CSV convient pour les enregistrements simples, possédant peu de champs et de références, mais surtout dans le cas où de très nombreux enregistrements doivent être importés (chargement par lot, très rapide). Les fichiers contenant les données de base à importer doivent être listés dans la clé data du fichier __manifest__.py et les données de démonstration dans la clé demo. Il est également recommandé de créer 2 sous-dossiers différents (data et demo) dans le dossier du module et d’y stocker les fichiers XML ou CSV contenant les données. Dans le cas d’un fichier XML, le nom du fichier doit être composé du nom du modèle (objet) suivi de _demo pour les données de démonstration et _data pour les données de base.
Dans le cas de notre module, nous allons créer quelques diplômes et étudiants par défaut (i.e. qui seront toujours insérés). Nous créerons des fichiers au format XML, format plus communément utilisé. Le fichier XML contient des balises record (une balise record par enregistrement) dans un élément data intégré dans un élément odoo. Un record représente un enregistrement pour le modèle spécifié́ dans son attribut model et dont l'identifiant externe est indiqué́ par l'attribut id. Un record contient des éléments field représentant un champ de l'enregistrement. Chaque élément field possède obligatoirement un attribut name qui indique le nom de la colonne concernée. La valeur du champ peut être fournie soit dans le corps de l'élément field, soit via l'attribut ref qui fait référence à l'identifiant externe d'un enregistrement existant (utilisé pour les champs many2one notamment).
Exercice 9
Créer un dossier data à la racine du module. Les fichiers XML devront y être stockés.
Créer le fichier XML nommé students_training_data.xml. Ce fichier contiendra les informations suivantes :
Créer le fichier XML nommé students_student_data.xml. Ce fichier contiendra les informations suivantes :

Modifier le fichier __manifest__.py:
Remarques :
Pour des données de démonstration, le contenu du fichier
__manifest__.pyaurait été le suivant :{ "name": "Gestion des étudiants", "version": "0.1", "category": "Generic Modules/Others", "description": """Test création module gestion des étudiants Odoo v14""", "author": "Moi", "depends": ["base"], "data": [ "views/student_view.xml", "views/training_view.xml", "views/students_menu.xml", ], "demo": [ "demo/students_training_data.xml", "demo/students_student_data.xml", ] "installable": True, "auto_install": False, }ATTENTION à l’ordre des fichiers de données dans les clés data et demo qui doit respecter les références entre les données.
Installer le module.
Résultat : 

Désinstaller le module. Stopper le projet Python.
Exercice 10 : Travail à faire
Vous créerez dans le casier nommé M3301_ODOO_PROGTD1_Gxx un dossier contenant votre nom.
Y créer un fichier Word contenant les copies d’écran présentant votre module (au minimum les copies d’écran présentées plus bas en exemples).
Conserver votre code pour la prochaine séance.
Intégrer la gestion des notes des étudiants. Pour faire simple, il y aura une matière (subject) et une note (mark) à saisir pour chaque étudiant. Exemple : Programmation Python, 10 ; Communication, 15.5. Il sera bien sûr possible de saisir plusieurs matières (et donc plusieurs notes) par étudiant.

Compléter le module précédent permettant la prise en compte des notes :
Ajouter un objet métier pour gérer les notes. Vous afficherez le n° INE (number) de l’étudiant dans la liste déroulante (cf. copies d’écran ci-dessous) dans le formulaire de saisie d’une note. Tous les champs sont obligatoires (y compris le n° d’étudiant). Remarque : pour mentionner plusieurs paramètres optionnels d’un champ, il faut les séparer par des virgules.
Modifier l’objet métier Student (classe StudentsStudent)
Créer l’interface (cf. écrans suivants) et compléter la traduction française.
Ajouter des données de démonstration (exemples de notes). Passer les étudiants en données de démonstration. Seules les diplômes resteront en données de base.
Dossier du projet complet : 
Pour traduire les nouveaux champs, il faut regenerer un fichier .pot (suivre indications de l'exerice 7). Vous pouvez ensuite remplacer l'ancien fichier .pot par le nouveau dans le dossier i18n. Pour faire les traductions, il faut ouvrir le fichier fr.po avec Poedit et cliquer dans le menu sur : Translation > update from POT file et choisir le fichier students.pot. Vous pouvez ensuite faire les traductions et sauvegarder le fichier.
Ecrans: 

Test de saisie d’une matière et d’une note. On remarque que la saisie de l’étudiant est obligatoire. 


Conserver votre code pour la prochaine séance.