1. Créez le fichier du modèle
Dans le module training_hello, créez le fichier models/training_note.py. Choisissez le préfixe training. afin d'éviter un nom trop général, qui pourrait déjà être utilisé par un autre module.
from odoo import fields, models
class TrainingNote(models.Model):
_name = "training.note"
_description = "Note de formation"
_order = "id desc"
title = fields.Char(string="Titre", required=True)
body = fields.Text(string="Contenu")Comment lire les deux premières lignes
from odoo import fields, models rend disponibles deux éléments fournis par Odoo. fields sert à déclarer les champs, par exemple fields.Char et fields.Text. models donne accès à la classe Model.
Dans class TrainingNote(models.Model):, models.Model n'est pas un paramètre. C'est la classe parente : en Python, les parenthèses après le nom d'une classe indiquent de quelle classe elle hérite. C'est comme class Voiture(Vehicule): : une voiture hérite des capacités d'un véhicule.
Ici, TrainingNote hérite des capacités d'un modèle Odoo : créer, rechercher, modifier et supprimer des notes. Lorsque le module charge ce fichier, Odoo enregistre aussi cette nouvelle classe comme modèle training.note. Vous n'appelez pas models.Model directement ; Python et Odoo l'utilisent pour construire votre modèle.
_nameest le nom technique du modèle. C'est celui qu'utiliseront le XML, l'ORM et les droits d'accès._descriptionest le nom compréhensible par les personnes qui administrent Odoo.titleetbodysont des champs stockés par défaut : Odoo leur créera une place dans la base de données._orderdemande d'afficher les notes dont l'identifiant est le plus élevé en premier. Ce n'est pas un champ de date.
Ce n'est pas une règle du type « tout attribut Python sans _ devient une colonne ». fields.Char(...) et fields.Text(...) créent des objets Field particuliers. Lorsque Python construit la classe, ces objets indiquent à Odoo leur nom — ici title et body — et Odoo les ajoute à la définition du modèle. Une variable ordinaire ou une méthode Python n'est pas un field. Les noms qui commencent par _, comme _name et _order, sont des directives spéciales pour Odoo ; ce ne sont pas des colonnes. Lors de la mise à niveau, Odoo utilise donc le type du Field, et non le seul nom de l'attribut, pour adapter la table PostgreSQL.
2. Indiquez à Python quels fichiers charger
Le simple fait de créer un fichier ne suffit pas. Python doit savoir qu'il doit charger le modèle : importez d'abord training_note dans le dossier models, puis importez ce dossier à la racine du module. Le module contient déjà le contrôleur créé au jour 1 : conservez aussi son import.
Importez le fichier du modèle
Dans models/__init__.py, ajoutez cette ligne. L'extrait suivant indique où la placer ; les # ... représentent d'éventuelles lignes déjà présentes.
# ...
from . import training_note # ← ajoutez cette ligne
# ...Pour copier uniquement la ligne à ajouter :
from . import training_noteImportez le dossier models à la racine du module
Dans le fichier __init__.py placé à la racine du module, gardez l'import du contrôleur du jour 1 et ajoutez l'import du dossier models.
from . import controllers
# ...
from . import models # ← ajoutez cette ligne
# ...Pour copier uniquement la ligne à ajouter :
from . import modelsPour utiliser un modèle dans l'interface interne d'Odoo, nous n'avons pas besoin de contrôleur HTTP. Un contrôleur servira plus tard lorsqu'une URL devra afficher une page web publique.
3. Redémarrez Odoo, puis mettez le module à jour
Redémarrez Odoo si votre environnement ne recharge pas automatiquement les fichiers Python. Dans Apps, ouvrez ensuite Hello Odoo et choisissez Mettre à niveau. Le redémarrage relit le code ; la mise à niveau enregistre les changements du modèle dans votre base d'exercice.
À vérifier : si vous avez suivi le préambule, actualisez l'arborescence de pgAdmin. Sous training → Schemas → public → Tables, la table training_note apparaît. Elle existe parce qu'Odoo a chargé la classe en suivant les deux imports, puis a adapté PostgreSQL pendant la mise à niveau.
Regardez les colonnes créées
Le nom de la table est un premier indice. Lisez aussi ses colonnes dans pgAdmin, avec Query Tool, ou dans psql connecté à la base d'exercice :
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'training_note'
ORDER BY ordinal_position;Résultat attendu : vous voyez notamment id, title et body, ainsi que des colonnes techniques comme create_date et write_date. Le point dans training.note devient un underscore dans le nom de table training_note.
À ce stade : il n'y a pas encore de menu. C'est normal : nous avons créé le modèle qui organisera les données avant de créer l'écran qui les affichera.