Étape 2 sur 3 · 35 min

Associer les formations aux notes du jour 2

Chaque formation aura un nom, une description et des notes associées. Le field Many2many créera ces liens sans copier les records de training.note.

1. Créez le model de formations

Créez un fichier dédié. ElearningModule est le nom de la classe Python ; elearning.module est le nom technique du model dans l’ORM. Chaque record de ce model correspond à une formation.

custom_addons/elearning_portal/models/elearning_module.py
from odoo import fields, models


class ElearningModule(models.Model):
    _name = "elearning.module"
    _description = "Formation eLearning"
    _order = "name"

    name = fields.Char(string="Nom", required=True)
    description = fields.Text(string="Description")
    note_ids = fields.Many2many(
        "training.note",
        string="Notes associées",
    )

Le premier paramètre de Many2many désigne le model existant. Odoo créera une table de relation pour mémoriser chaque paire « formation–note ». Les titres et les contenus restent, eux, dans la table training_note.

Ne redéfinissez pas training.note

Ne recopiez pas la classe du jour 2 et ne créez pas un nouveau field title dans cet addon. training_hello charge déjà ce model ; grâce à la dépendance, vous pouvez l’utiliser dans le field note_ids.

À observer : une formation pourra être liée à plusieurs notes et une même note pourra servir à plusieurs formations. Supprimer un lien ne supprime pas automatiquement la note.

2. Indiquez à Odoo où trouver le model

Pour qu’Odoo charge votre model, Python doit suivre les imports jusqu’au fichier qui contient la classe. Remplacez le contenu des deux fichiers d’import par les lignes suivantes.

custom_addons/elearning_portal/models/__init__.py
from . import elearning_module
custom_addons/elearning_portal/__init__.py
from . import models

Le fichier racine importe le package models, qui importe ensuite elearning_module.py. C’est ainsi qu’Odoo finit par charger votre classe.

Résultat attendu : au prochain redémarrage, Odoo pourra enregistrer le model elearning.module. Vous n’importez pas encore de contrôleur, puisqu’aucune route n’existe à ce stade.

3. Ajoutez deux formations de démonstration

Les trois notes de départ possèdent déjà des external IDs stables. Le scaffold ne crée pas toujours le dossier data/ : s’il manque, créez custom_addons/elearning_portal/data/, puis ajoutez le fichier suivant. Il définit deux formations fictives liées à ces notes connues.

custom_addons/elearning_portal/data/elearning_module_data.xml
<?xml version="1.0" encoding="UTF-8"?>
<odoo noupdate="1">
    <record id="elearning_module_odoo_basics" model="elearning.module">
        <field name="name">Bases du développement Odoo</field>
        <field name="description">Comprendre un model, ses données et sa mise à niveau.</field>
        <field name="note_ids"
               search="[('id', 'in', [
                   ref('training_hello.training_note_welcome'),
                   ref('training_hello.training_note_observe'),
               ])]"/>
    </record>

    <record id="elearning_module_safe_practice" model="elearning.module">
        <field name="name">Pratiquer dans une base d’exercice</field>
        <field name="description">Tester les changements sans utiliser de données réelles.</field>
        <field name="note_ids"
               search="[('id', 'in', [
                   ref('training_hello.training_note_test'),
               ])]"/>
    </record>
</odoo>

La propriété search demande à Odoo de retrouver les notes indiquées. Chaque ref(...) transforme un external ID en identifiant de record ; le préfixe training_hello. est indispensable, car les notes appartiennent à l’autre addon. Odoo associe ensuite les résultats de cette recherche à note_ids.

Vous n’avez pas besoin d’apprendre les commandes relationnelles à trois nombres dans cette étape. Elles sont utiles plus tard, dans certains cas précis, mais elles n’aident pas à comprendre cette première relation.

noupdate="1" préserve ensuite les ajustements réalisés dans l’interface : une mise à niveau ultérieure ne réécrit pas ces relations de départ.

Ce que garantit la dépendance

Odoo charge training_hello avant ce fichier. Il peut donc retrouver les trois external IDs. Le XML ne duplique ni le titre ni le contenu des notes : il enregistre seulement les liens entre les records.

4. Attendez avant de mettre l’addon à niveau

Le fichier de données est prêt. À l’étape suivante, vous créerez d’abord l’ACL, ou Access Control List : c’est le fichier qui indique à Odoo quels utilisateurs peuvent lire ou modifier les formations. Dans cet exercice, il s’agit de custom_addons/elearning_portal/security/ir.model.access.csv. Vous créerez ensuite les views, puis ajouterez tous les chemins à data dans le manifeste. Vous installerez ainsi l’addon d’un seul coup, avec les écrans et les droits nécessaires.

À vérifier maintenant :

  • custom_addons/elearning_portal/models/elearning_module.py contient exactement un model elearning.module ;
  • custom_addons/elearning_portal/models/__init__.py importe elearning_module ;
  • custom_addons/elearning_portal/__init__.py importe models ;
  • custom_addons/elearning_portal/data/elearning_module_data.xml référence les external IDs préfixés par training_hello..
Résultat attendu

Votre code décrit un nouveau model de formations et sa relation avec le model du jour 2. Les fichiers sont prêts, mais vous n’avez encore ni menu ni droit d’accès pour ouvrir ces formations.