Se rendre au contenu

Champ One2many dans Odoo : Guide Complet pour Développeurs

Comprendre le rôle du champ One2many dans Odoo : quand l’adopter et comment l’intégrer à votre modèle de données Le champ One2many sert à modéliser une relation un-à-plusieurs entre deux objets métiers dans Odoo. Concrètement, il permet d’associer une collection d’enregistrements « enfants » à un enregistrement « parent » — par exemple, plusieurs lignes de commande liées à une seule commande, ou plusieurs rendez-vous rattachés à un même client. Ce champ ne stocke pas directement les données sur le modèle parent : il reflète plutôt l’ensemble des enregistrements du modèle enfant qui pointent vers ce parent via un champ Many2one. Quand l’utiliser Optez pour One2many quand vous devez représenter un ensemble d’éléments dépendants d’un objet principal et que ces éléments existent en tant qu’entités autonomes (avec leurs propres champs, règles et workflows). Exemples typiques : lignes d’une facture, adresses d’un contact, tâches d’un projet, ou pièces jointes d’un dossier. Si les sous-éléments n’ont pas d’existence propre ou si vous ne voulez pas gérer des enregistrements distincts, une structure imbriquée ou un champ JSON peut être plus adaptée. Comment l’implémenter dans votre modèle Python 1) Créez d’abord le modèle enfant avec un Many2one pointant vers le parent : - Dans le modèle enfant, définissez field_parent = fields.Many2one('votre.parent', string='Parent', ondelete='cascade') - Ce Many2one contient la clé étrangère réelle en base de données. 2) Déclarez le One2many sur le modèle parent en référence au champ Many2one du modèle enfant : - Dans le modèle parent, écrivez children_ids = fields.One2many('votre.enfant', 'field_parent', string='Éléments') - Le second argument ('field_parent') indique le champ Many2one dans le modèle enfant qui relie les deux modèles. Conception de la base de données et performance Le One2many n’ajoute pas de colonne supplémentaire au parent : la relation est matérialisée par la colonne Many2one dans la table enfant. Les opérations de lecture impliquent souvent des jointures ou des requêtes séparées pour récupérer les enregistrements enfants, ce qui peut impacter les performances si vous chargez de gros volumes. Prévoyez des index sur les colonnes Many2one et limitez le chargement (lazy loading, domain, limit) lorsque nécessaire. Comportement dans les vues et formulaires Dans les vues formulaire, le One2many s’affiche généralement comme une liste ou une grille embarquée, avec la possibilité d’ajouter/modifier/supprimer les enregistrements enfants directement depuis le parent. Vous pouvez configurer le mode d’affichage (tree, form, kanban), appliquer des domaines pour filtrer les lignes visibles, et définir des attributs comme readonly, required, ou context pour contrôler l’expérience utilisateur. Synchronisation et règles d’intégrité Utilisez ondelete='cascade' sur le Many2one si vous souhaitez que la suppression du parent entraîne celle des enfants. Pour des besoins plus fins, gérez la suppression et la validation via des contraintes SQL ou des méthodes Python (unlink, write, create) afin d’assurer l’intégrité métier. Exemples pratiques et bonnes pratiques - Facturation : une facture (parent) avec ses lignes (One2many) ; indexez invoice_id dans account_invoice_line. - CRM : un contact avec plusieurs adresses ; limitez l’affichage si un contact peut avoir des centaines d’adresses. - Performance : évitez d’afficher des One2many contenant des milliers de lignes dans une même vue ; préférez des vues filtrées ou une liaison vers une liste séparée. Test et migration Lors de la migration de schéma, vérifiez que les données du modèle enfant conservent la référence Many2one valide et recréez les index si nécessaire. Écrivez des tests unitaires pour les scénarios create/write/unlink sur les deux modèles afin de confirmer le comportement attendu. En résumé Le champ One2many est l’outil standard d’Odoo pour représenter des collections d’enregistrements liés à un parent. Il est idéal quand les éléments enfants ont une existence propre et des règles métiers distinctes. Pour l’utiliser efficacement, pensez à la conception des index, au contrôle du chargement des données dans les vues, et aux règles de gestion (suppression, contraintes) qui garantissent l’intégrité de votre modèle.
6 mars 2026 par
Champ One2many dans Odoo : Guide Complet pour Développeurs
Dasolo
| Aucun commentaire pour l'instant

Introduction


Si, en ouvrant une commande client dans Odoo, vous avez déjà ajouté, modifié ou supprimé des lignes directement depuis la fiche sans changer d’écran, vous avez utilisé un One2many. C’est un mécanisme central du modèle de données Odoo : il permet d’agréger plusieurs enregistrements enfants autour d’un seul enregistrement parent, et comprend à la fois l’ergonomie et la logique relationnelle derrière de nombreuses vues de l’ERP.


Ce guide présente l’essentiel à connaître : ce qu’est concrètement un One2many, comment l’ORM d’Odoo le matérialise, dans quels scénarios l’utiliser, et comment le mettre en place soit via Odoo Studio sans code, soit en le définissant directement dans un module Python.

Que vous soyez utilisateur métier curieux de la structure de vos données ou développeur en quête d’un tutoriel pratique sur les champs Odoo, ce texte synthétise les points utiles pour maîtriser le One2many.

Qu’est-ce que le champ One2many dans Odoo


Un One2many est un type de champ relationnel dans Odoo qui représente une relation parent → plusieurs enfants. Il donne l’illusion, dans le modèle parent, d’une liste d’éléments liés provenant d’un autre modèle.


Concrètement : une facture peut contenir plusieurs lignes, une commande plusieurs positions, un projet plusieurs tâches. Le parent ne stocke pas physiquement ces lignes ; il présente simplement l’ensemble des enregistrements enfants qui lui sont associés.


Dans l’interface, le One2many se manifeste le plus souvent comme une liste intégrée dans une vue formulaire. Cette table embarquée permet de créer, éditer ou supprimer des éléments enfants sans quitter la fiche parent — un usage très courant dans les modules commerciaux, comptables ou projets.


Différence avec les autres champs relationnels

L’ORM d’Odoo propose trois relations majeures :


  • Many2one : un enregistrement fait référence à un unique enregistrement d’un autre modèle (ex. : une commande vers un client).
  • One2many : un enregistrement regroupe plusieurs enregistrements d’un autre modèle (ex. : une commande vers ses lignes).
  • Many2many : relation multiple réciproque où chaque côté peut référencer plusieurs enregistrements de l’autre (ex. : produits et étiquettes).

Le One2many est approprié quand chaque enregistrement enfant n’appartient qu’à un seul parent. Si un enfant doit être partagé entre plusieurs parents, il faut plutôt opter pour un Many2many.


Particularité importante : le One2many n’est pas une colonne physique. C’est un champ virtuel qui s’appuie sur la présence d’un Many2one dans le modèle enfant pour effectuer la liaison.

Fonctionnement du champ


En base de données, rien n’est ajouté à la table du parent pour un One2many. Les relations sont matérialisées par une clé étrangère dans la table de l’enfant, via un champ Many2one qui pointe vers l’ID du parent.


Principe clé de l’ORM Odoo : chaque One2many correspond à un Many2one inverse sur le modèle lié. Le One2many n’est qu’une recherche inversée des enregistrements enfants dont le Many2one vaut l’ID du parent courant.


La relation One2many ↔ Many2one

Lors de la définition d’un One2many en Python, deux paramètres sont indispensables :


  • comodel_name : le nom du modèle qui contient les enregistrements enfants.
  • inverse_name : le nom du champ Many2one sur l’enfant qui renvoie vers le parent.

Par exemple, pour lier un contrat de service à ses livrables, on déclare un champ One2many sur le contrat qui pointe vers le modèle des livrables.


deliverable_ids = fields.One2many(
    comodel_name='service.deliverable',
    inverse_name='contract_id',
    string='Deliverables'
)

Ici, contract_id est le Many2one défini sur service.deliverable qui référence le contrat. Sans ce Many2one, le One2many ne peut pas exister.


Ce que cela implique en base de données

La donnée effective des relations est stockée dans la table de l’enfant : chaque ligne enfant contient une colonne de clé étrangère pointant vers l’ID du parent. La table du parent ne reçoit pas de colonne supplémentaire pour le One2many.

Quand Odoo charge une fiche parent et doit afficher son One2many, l’ORM exécute une requête qui récupère toutes les lignes enfants dont la clé étrangère correspond à l’ID du parent — comportement standard des bases relationnelles, géré automatiquement par Odoo.


C’est pour cette raison que le One2many est considéré comme un champ calculé : il offre simplement une vue agrégée des enregistrements liés via l’inverse Many2one.

Cas d’usage en entreprise


Exemples pratiques courants


1. Commandes clients et positions

Dans le module Ventes, la commande (sale.order) possède un One2many order_line_ids vers sale.order.line. Chaque ligne contient produit, quantité, prix unitaire et remise, et se gère directement depuis la fiche commande.


2. Factures et lignes de facture

En comptabilité, le modèle account.move agrège ses lignes (account.move.line) via un One2many ; la facture calcule ses montants à partir des lignes enfants.


3. Projets et tâches

Le modèle project.project affiche ses tâches grâce à un One2many. Selon la vue vous verrez la liste, le kanban ou même le diagramme de Gantt, tous basés sur la même relation sous-jacente.


4. Entreprises et contacts liés

res.partner expose un champ child_ids listant les contacts liés à une société. Chaque contact porte un parent_id Many2one qui renvoie à l’entreprise.


5. Modèles personnalisés (service, production…)

Dans des modules sur-mesure, le One2many est l’outil naturel pour représenter des listes d’éléments dépendant d’un enregistrement : pièces d’un bon de maintenance, sessions d’un cours, livrables d’un contrat de service, etc.


Grâce à cette flexibilité, le One2many est omniprésent dans les personnalisations Odoo et facilite l’adaptation de l’ERP à des secteurs variés.

Créer ou personnaliser le champ


Deux méthodes principales existent pour créer un One2many : via Odoo Studio pour éviter le code, ou directement dans un module Python pour un contrôle total.


Créer un One2many avec Odoo Studio

Studio n’autorise pas la création d’un One2many directement depuis le parent si le Many2one inverse n’existe pas déjà sur l’enfant — la dépendance inverse est obligatoire.

Procédure recommandée dans Studio :

  1. Ouvrir d’abord le modèle enfant et y ajouter un champ Many2one pointant vers le parent.
  2. Sauver ce champ, puis revenir sur le modèle parent dans Studio.
  3. Créer un nouveau champ de type One2many : Studio vous demandera le modèle lié et le nom du champ inverse Many2one.
  4. Le One2many apparaît ensuite comme une liste intégrée dans la vue formulaire du parent.

Pour de nombreux utilisateurs métiers, c’est la méthode la plus simple pour établir des relations sans écrire de code ; le comportement est équivalent aux définitions Python.


Créer un One2many en Python (module personnalisé)

Pour les développeurs, définir le One2many dans un module offre plus de maîtrise sur le nommage, le comportement et les filtres (domain). Exemple complet :


from odoo import fields, models

class ServiceContract(models.Model):
    _name = 'service.contract'
    _description = 'Service Contract'

    name = fields.Char(string='Contract Name', required=True)
    deliverable_ids = fields.One2many(
        comodel_name='service.deliverable',
        inverse_name='contract_id',
        string='Deliverables'
    )


class ServiceDeliverable(models.Model):
    _name = 'service.deliverable'
    _description = 'Service Deliverable'

    contract_id = fields.Many2one(
        comodel_name='service.contract',
        string='Contract',
        ondelete='cascade'
    )
    name = fields.Char(string='Description', required=True)

Observez que le Many2one (contract_id) est défini sur le modèle enfant. L’inverse_name du One2many doit correspondre exactement au nom du champ Many2one.


Création via l’API XML-RPC

Si vous automatisez la gestion des champs ou administrez des bases Odoo à grande échelle, il est possible de créer des champs (dont One2many) via l’API XML-RPC en manipulant le modèle ir.model.fields. La règle reste identique : créer d’abord le Many2one puis référencer son nom dans le One2many via le paramètre relation_field.


Cette méthode est pratique pour déployer des personnalisations sur plusieurs environnements ou intégrer la configuration dans des scripts d’automatisation.

Bonnes pratiques


Bonnes pratiques issues de retours terrain


  • Toujours créer le Many2one en premier. Qu’il s’agisse de Studio, de code Python ou de l’API, le champ inverse doit exister avant le One2many.
  • Respecter la convention de nommage avec le suffixe _ids. Noms comme line_ids, task_ids ou deliverable_ids indiquent immédiatement qu’il s’agit d’un recordset.
  • Préciser ondelete='cascade' quand c’est pertinent. Si les enfants doivent disparaître quand le parent est supprimé, activez cette option sur le Many2one pour éviter des enregistrements orphelins.
  • Rester sélectif dans la liste intégrée. N’affichez que les colonnes utiles : trop d’informations alourdit la fiche et ralentit l’affichage. Utilisez des colonnes optionnelles pour les champs secondaires.
  • Appliquer des domain pour filtrer les enfants visibles. Quand un modèle enfant peut être partagé entre plusieurs parents, un domain permet de n’afficher que les enregistrements pertinents.
  • Gérer les grands volumes avec prudence. Si un parent peut posséder des milliers d’enfants, évitez de tout charger dans la vue formulaire : préférez une vue liste séparée, une pagination ou des recherches ciblées.

Pièges fréquents


Pièges et erreurs fréquentes


Oublier le Many2one inverse

L’erreur la plus fréquente est de définir un One2many sans que le Many2one correspondant existe sur le modèle enfant. Odoo lèvera une exception. Vérifiez toujours que l’inverse_name que vous indiquez est bien présent sur le modèle lié.


Mauvaise syntaxe d’écriture (write)

Pour modifier un One2many par code ou via l’API, il faut utiliser la syntaxe des tuples de commandes Odoo. On ne peut pas assigner une simple liste Python au champ One2many.


  • (0, 0, values_dict) pour créer un nouvel enfant.
  • (1, child_id, values_dict) pour mettre à jour un enfant existant.
  • (2, child_id, 0) pour supprimer un enfant et le supprimer définitivement.
  • (4, child_id, 0) pour lier un enfant existant à la relation.
  • (5, 0, 0) pour délier tous les enfants du parent sans les supprimer.

Tenter quelque chose comme record.line_ids = [1, 2, 3] ne fonctionnera pas ; il faut passer par les commandes Odoo adaptées.


Confondre One2many et Many2many

Un One2many implique une appartenance exclusive : chaque enfant n’a qu’un parent. Si un enregistrement doit être lié à plusieurs parents, utilisez un Many2many. Forcer un One2many dans ce cas vous obligera à dupliquer des enregistrements et nuira à l’intégrité des données.


Problèmes de performance sur de longues listes

Afficher des centaines ou des milliers de lignes dans un One2many ralentit fortement le chargement des formulaires — problème classique en comptabilité ou gestion des stocks. Utilisez des limites dans la vue, des filtres ou redirigez vers une liste dédiée pour les gros volumes.


Enregistrements orphelins après suppression

Si vous supprimez un parent sans avoir défini ondelete='cascade' sur le Many2one, les enfants peuvent rester avec une référence nulle ou invalide. À terme cela encombre la base et provoque des comportements inattendus dans les vues et rapports. Définissez une stratégie de suppression claire lors de la conception du modèle.

Conclusion


Le One2many est un pilier du modèle de données Odoo. Il alimente des fonctionnalités clefs — lignes de commande, lignes de facture, tâches de projet — et devient rapidement intuitif dès qu’on comprend son dépendance au Many2one inverse. Maîtriser ce couple relationnel rend la structure interne d’Odoo beaucoup plus lisible et extensible.


Que vous configuriez Odoo pour votre activité, que vous utilisiez Studio ou développiez un module sur-mesure, le One2many restera un outil courant. Savoir quand l’employer, comment le déclarer et comment éviter les erreurs classiques vous fera gagner du temps et préservera la qualité de vos données.

Pour approfondir, consultez les autres ressources et tutoriels de la collection « Données & API Odoo » pour des exemples pratiques et des guides techniques supplémentaires.

Besoin d’aide pour votre projet Odoo ?


Dasolo accompagne les entreprises dans l’implémentation, la personnalisation et l’optimisation d’Odoo selon leurs besoins. Que ce soit pour concevoir un modèle de données, développer un module, créer des champs ou tirer davantage de valeur de votre installation, notre équipe peut vous assister.

Si vous avez des questions sur votre projet Odoo ou souhaitez discuter de la meilleure façon d’organiser vos données, contactez-nous— nous serons ravis de vous aider.

Champ One2many dans Odoo : Guide Complet pour Développeurs
Dasolo 6 mars 2026
Partager cet article
Se connecter pour laisser un commentaire.