1. Donnez les droits minimaux
Une vue ne donne pas le droit de manipuler les données. Pour la formation, les utilisateurs internes peuvent gérer les notes et les catégories. Nous détaillerons les droits plus fins au jour 5.
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_training_note_user,training.note user,model_training_note,base.group_user,1,1,1,1
access_training_note_category_user,training.note.category user,model_training_note_category,base.group_user,1,1,1,1Le module créé au début de la formation peut contenir une ancienne règle d'exemple pour le modèle training_hello.training_hello. Ce modèle n'existe plus lorsque sa classe est commentée : laissez cette ancienne ligne dans le CSV et la mise à niveau échouera, même si les deux lignes de notes sont justes.
access_training_hello_training_hello,training_hello.training_hello,model_training_hello_training_hello,base.group_user,1,1,1,1Gardez la ligne d'en-tête, puis faites en sorte que les deux lignes access_training_note_... ci-dessus soient les seules règles de ce fichier pour cet exercice.

1 pour les notes comme pour les catégories.Lire la première ligne, cellule par cellule
La première ligne de données accorde les droits sur les notes. Une virgule sépare chaque cellule :
access_training_note_user,training.note user,model_training_note,base.group_user,1,1,1,1| Cellule | Valeur | Ce qu'elle désigne |
|---|---|---|
id | access_training_note_user | L'identifiant externe de cette règle d'accès. Il permet à Odoo de retrouver cette même règle lors d'une mise à niveau. |
name | training.note user | Un libellé lisible par les personnes qui administrent Odoo. Il n'est pas utilisé pour décider l'accès. |
model_id:id | model_training_note | model_id est le champ de la règle qui pointe vers la fiche du modèle dans ir.model ; :id demande à Odoo de résoudre la valeur comme un identifiant externe. model_training_note est sa forme courte dans ce module : Odoo la résout en training_hello.model_training_note. |
group_id:id | base.group_user | Le groupe Odoo des utilisateurs internes. Seuls les membres de ce groupe reçoivent cette règle. |
perm_read, perm_write, perm_create, perm_unlink | 1,1,1,1 | Quatre indicateurs : lire, modifier, créer et supprimer. 1 autorise l'opération ; 0 la refuse. |
model_training_noteLe nom technique du modèle, celui que nous avons écrit en Python, est training.note. Sa table PostgreSQL est training_note. Pour référencer la fiche qui décrit ce modèle dans ir.model, Odoo crée l'identifiant externe training_hello.model_training_note : nom du module training_hello, puis model_, puis training.note avec le point remplacé par un tiret bas.
Donc non : model n'est pas la valeur de model_id. C'est seulement le préfixe de cet identifiant externe généré. La valeur de la colonne model_id:id est bien la référence model_training_note, qui mène à la fiche ir.model de training.note.
Un fichier CSV reste du texte, mais ses nombreuses colonnes sont plus faciles à vérifier dans une vue en tableau. Dans VS Code, vous pouvez installer l'extension facultative CSV de ReprEng depuis le Marketplace, puis rouvrir ir.model.access.csv. Elle aide à repérer les colonnes et les valeurs 1, sans modifier le rôle du fichier dans Odoo.
Gardez le bon réflexe : l'extension n'accorde aucun droit, ne valide pas la sécurité Odoo et ne remplace pas le CSV versionné. Avant d'enregistrer, vérifiez toujours la ligne d'en-tête et chaque identifiant technique dans le texte du fichier.
2. Créez les listes, les fiches et les menus
Un clic dans une liste ouvre la fiche correspondante. Les deux modèles reçoivent leur propre action et leur propre entrée de menu : les catégories sont donc administrables sans SQL.
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="training_note_category_view_list" model="ir.ui.view">
<field name="name">training.note.category.list</field>
<field name="model">training.note.category</field>
<field name="arch" type="xml">
<list><field name="name"/></list>
</field>
</record>
<record id="training_note_category_view_form" model="ir.ui.view">
<field name="name">training.note.category.form</field>
<field name="model">training.note.category</field>
<field name="arch" type="xml">
<form><sheet><group><field name="name"/></group></sheet></form>
</field>
</record>
<record id="training_note_view_list" model="ir.ui.view">
<field name="name">training.note.list</field>
<field name="model">training.note</field>
<field name="arch" type="xml">
<list>
<field name="title"/>
<field name="category_id"/>
</list>
</field>
</record>
<record id="training_note_view_form" model="ir.ui.view">
<field name="name">training.note.form</field>
<field name="model">training.note</field>
<field name="arch" type="xml">
<form><sheet><group>
<field name="title"/>
<field name="category_id"/>
<field name="body"/>
</group></sheet></form>
</field>
</record>
<record id="training_note_action" model="ir.actions.act_window">
<field name="name">Notes</field>
<field name="res_model">training.note</field>
<field name="view_mode">list,form</field>
</record>
<record id="training_note_category_action" model="ir.actions.act_window">
<field name="name">Catégories</field>
<field name="res_model">training.note.category</field>
<field name="view_mode">list,form</field>
</record>
<menuitem id="training_note_menu_root" name="Notes de formation" sequence="30"/>
<menuitem id="training_note_menu" name="Notes" parent="training_note_menu_root" action="training_note_action" sequence="10"/>
<menuitem id="training_note_category_menu" name="Catégories" parent="training_note_menu_root" action="training_note_category_action" sequence="20"/>
</odoo>En Odoo 19, utilisez <list>, pas l'ancien nom <tree>. Le field category_id devient un choix de catégories dans le formulaire : Odoo affiche leur nom, mais enregistre leur identifiant dans la note.
3. Déclarez les fichiers dans le manifeste
Ajoutez ces deux fichiers après les données XML. Conservez toutes les entrées déjà présentes : le manifeste est la liste complète des fichiers qu'Odoo charge.
data"data": [
# ...
"security/ir.model.access.csv", # ← ajoutez cette ligne
"views/training_note_views.xml", # ← ajoutez cette ligne
# ...
],Pour copier uniquement les deux lignes :
"security/ir.model.access.csv",
"views/training_note_views.xml",data complète"data": [
"views/hello_world_menus.xml",
"data/partner_category_data.xml",
"views/partner_category_list.xml",
"data/training_note_data.xml",
"data/training_note_category_data.xml",
"security/ir.model.access.csv",
"views/training_note_views.xml",
],4. Rechargez correctement, puis ouvrez l'application
La mise à niveau du module est indispensable : elle importe le CSV des droits et le XML des vues dans la base. Un simple rechargement du navigateur ne suffit pas.
- Vous avez ajouté un fichier ou modifié
__manifest__.py: redémarrez Odoo si votre lancement ne recharge pas automatiquement les fichiers. - Dans Apps, cherchez Hello Odoo, puis cliquez sur Mettre à niveau.
Si vous avez seulement modifié une ligne dans un CSV ou un XML déjà déclaré, le redémarrage n'est généralement pas nécessaire ; faites tout de même la mise à niveau du module. Dans le lanceur d'applications, ouvrez ensuite Notes de formation. Vous devez voir les deux menus Notes et Catégories.
model_training_hello_training_hello »Cette erreur ne désigne pas les notes. Elle indique qu'Odoo lit encore l'ancienne ligne d'exemple ci-dessus : sa référence vise le modèle abandonné training_hello.training_hello. Supprimez cette ligne, enregistrez le CSV, puis mettez à niveau Hello Odoo. En revanche, model_training_note est la bonne référence pour le modèle que nous avons réellement créé : training.note.