Enable Dark Mode!
complete-overview-of-reference-and-many2onereference-fields-in-odoo-19.jpg
By: Swaraj R

Complete Overview of Reference and Many2oneReference Fields in Odoo 19

Technical Odoo 19 Odoo Enterprises Odoo Community

In modern Odoo development, flexibility is just as important as structure. While traditional relational fields like Many2one work perfectly when relationships are fixed, real-world business logic often demands something more dynamic. This is where Reference and Many2oneReference fields come into play.

These fields allow developers to build smart, adaptable relationships between models without being limited to a single predefined target, whether you're designing configurable workflows, generic linking mechanisms, or dynamic business rules, understanding how Reference and Many2oneReference fields work is essential for building scalable and future-proof Odoo applications.

Defining a Reference Field in Odoo 19

Below is a basic example of a Reference field definition:

class PersonalDetails(models.Model):
   _name = 'personal.details'
   _description = 'Personal Details'
   reference = fields.Reference(
       selection=[
           ('res.partner', 'Partner'),
           ('sale.order', 'Sales Order'),
           ('purchase.order', 'Purchase Order'),
       ],
       string="Related Document"
   )

How It Works

  • The dropdown shows Partner, Sales Order, and Purchase Order
  • Once selected, the user can choose a record from the selected model
  • The value is stored as <model_name>,<record_id>

Example stored value:

sale.order,24

Understanding selection in Reference Fields

The selection attribute defines the list of models that the Reference field can point to.

selection = [
    ('res.partner', 'Partner'),
    ('sale.order', 'Sales Order'),
]

Each tuple consists of:

  • The technical model name
  • The human-readable label

This mechanism ensures flexibility while still maintaining control over which models can be referenced.

Using selection_add with Reference Fields

Because Reference fields inherit from Selection fields, they support selection_add.

This allows other modules to extend the available models without overriding the field.

reference = fields.Reference(selection_add=[
   ('account.move', 'Invoice')
])

This is especially useful in modular Odoo development, where different modules may want to extend the same reference field safely.

The image below shows how it will be reflected in the form view

Complete Overview of Reference and Many2oneReference Fields in Odoo 19-cybrosys

Key Characteristics of Reference Fields

  • Can reference multiple models
  • Inherits behavior from Selection fields
  • Supports modular extension using selection_add
  • Stores values as model_name,record_id
  • Does not enforce database-level foreign keys
  • Slightly slower than Many2one for large datasets

When to Use Reference Fields

Reference fields are ideal when:

  • A record can relate to multiple possible models
  • You are building generic relationships
  • You need flexibility rather than strict relational enforcement

Common use cases include:

  • Activity logs
  • Audit trails
  • Communication history
  • Generic document linking

Many2one Reference Field in Odoo 19

The Many2oneReference field in Odoo 19 is a powerful and flexible relational field designed to handle dynamic relationships where the target model is not fixed at design time.

Unlike a standard Many2one field which always points to a single predefined model a Many2oneReference field determines which model to reference at runtime, based on the value of another field.

What is a Many2oneReference Field?

A Many2oneReference is a pseudo-relational field that behaves like a Many2one field but does not enforce a database-level foreign key.

Instead of directly linking to a model, it relies on:

  • A Char field that stores the model name
  • A Many2oneReference field that stores the record ID of that model

This design allows the record to dynamically link to different models, depending on the value stored in the model field.

This tells us three important things:

  1. The field stores an integer ID
  2. There is no database-level foreign key
  3. The actual model is resolved dynamically using another field

Core Concept: Model Field + Reference Field

A Many2oneReference always works together with a Char field that stores the model name.

Example Definition

m2o_reference_model = fields.Char(
   string='Reference Model',
   help="Technical name of the model to be used for the Many2one reference."
)
m2o_reference_id = fields.Many2oneReference(
   string='Related Record',
   model_field='m2o_reference_model',
   help="Select a record from the chosen reference model."
)

The image below shows how it will be reflected in the form view

Complete Overview of Reference and Many2oneReference Fields in Odoo 19-cybrosys

How This Works

  1. m2o_reference_model
    • Stores the technical model name (e.g., sale.order, purchase.order)
    • Acts as a controller for the reference field
  2. m2o_reference_id
    • Stores the ID of the selected record
    • Dynamically adapts based on the model defined in m2o_reference_model

How It Works in the User Interface

The user enters or selects a model name in the Reference Model field

Example:

The Related Record field automatically adapts and allows selection of:

  • Sale Orders if sale.order is entered
  • Purchase Orders if purchase.order is entered
  • Any other valid model name

This makes the field fully dynamic, allowing one record to link to different types of business documents.

Why Use Many2oneReference?

Advantages

  • Extremely flexible relationship handling
  • Ideal for dynamic or configurable workflows
  • No need to define multiple Many2one fields
  • Clean and extensible architecture

Considerations

  • No database-level foreign key enforcement
  • Model name must be valid and correctly typed
  • Requires careful UI validation for user input

When to Use Many2oneReference

Use Many2oneReference when:

  • The target model is not known in advance
  • The model is selected dynamically by the user
  • You want to build generic configuration systems
  • You need a more controlled alternative to Reference fields

Common use cases:

  • Workflow engines
  • Approval systems
  • Generic document linking
  • Configurable automation rules

Create a file named personal_details.py inside the models directory and add the following code:

# -*- coding: utf-8 -*-
from odoo import fields, models

class PersonalDetails(models.Model):
   _name = 'personal.details'
   _description = 'Personal Details'
   reference = fields.Reference(
       selection=[
           ('res.partner', 'Partner'),
           ('sale.order', 'Sales Order'),
           ('purchase.order', 'Purchase Order'),
       ],
       string="Related Document",
       help="Select a related document such as a Partner, Sales Order, or Purchase Order."
   )
   name = fields.Char(
       string='Name',
       required=True,
       help="Enter the full name of the person."
   )
   age = fields.Integer(
       string='Age',
       help="Enter the age of the person."
   )
   gender = fields.Selection(
       [
           ('male', 'Male'),
           ('female', 'Female'),
           ('other', 'Other')
       ],
       string='Gender',
       help="Select the gender of the person."
   )
   email = fields.Char(
       string='Email',
       help="Enter the email address of the person."
   )
   phone = fields.Char(
       string='Phone',
       help="Enter the contact phone number."
   )
   document_reference = fields.Reference(
       selection=[
           ('res.partner', 'Partner'),
           ('sale.order', 'Sale'),
           ('res.users', 'User'),
           ('product.product', 'Product')
       ],
       string='Document Reference',
       help="Link this record to another document such as a Partner, User, Sale, or Product."
   )
   m2o_reference_model = fields.Char(
       string='Reference Model',
       help="Technical name of the model to be used for the Many2one reference."
   )
   m2o_reference_id = fields.Many2oneReference(
       string='Related Record',
       model_field='m2o_reference_model',
       help="Select a record from the chosen reference model."
   )

In the views directory, create a new file named personal_details_views.xml and paste the code below.

<?xml version="1.0" encoding="utf-8"?>
<odoo>
   <data>
       <!-- list View -->
       <record id="view_personal_details_list" model="ir.ui.view">
           <field name="name">personal.details.list</field>
           <field name="model">personal.details</field>
           <field name="arch" type="xml">
               <list string="Personal Details">
                   <field name="name"/>
                   <field name="age"/>
                   <field name="gender"/>
                   <field name="email"/>
                   <field name="phone"/>
               </list>
           </field>
       </record>
       <!-- Form View -->
       <record id="view_personal_details_form" model="ir.ui.view">
           <field name="name">personal.details.form</field>
           <field name="model">personal.details</field>
           <field name="arch" type="xml">
               <form string="Personal Details">
                   <sheet>
                       <group>
                           <group>
                               <field name="name"/>
                               <field name="age"/>
                               <field name="gender"/>
                           </group>
                           <group>
                               <field name="email"/>
                               <field name="phone"/>
                           </group>
                       </group>
                       <group string="References">
                          <field name="reference"/>
                          <field name="m2o_reference_model"/>
                          <field name="m2o_reference_id"/>
                       </group>
                   </sheet>
               </form>
           </field>
       </record>
       <!-- Action -->
       <record id="action_personal_details" model="ir.actions.act_window">
           <field name="name">Personal Details</field>
           <field name="res_model">personal.details</field>
           <field name="view_mode">list,form</field>
           <field name="help" type="html">
               <p class="o_view_nocontent_smiling_face">
                   Create a new personal detail record.
               </p>
           </field>
       </record>
       <!-- Menu Item -->
       <menuitem id="menu_personal_details_root"
                 name="Personal Details"
                 sequence="10"/>
       <menuitem id="menu_personal_details"
                 name="Personal Details"
                 parent="menu_personal_details_root"
                 action="action_personal_details"
                 sequence="10"/>
   </data>
</odoo>

Both Reference and Many2oneReference fields play a crucial role in building flexible and scalable Odoo applications. While they differ in how they store and resolve relationships, their shared purpose is to overcome the limitations of fixed relational models and support dynamic business logic.

By using these fields appropriately, developers can design systems that adapt to evolving requirements, reduce unnecessary model dependencies, and support complex workflows with ease. When applied thoughtfully, Reference and Many2oneReference fields become powerful tools for creating modular, maintainable, and highly extensible Odoo solutions.

To read more about A Complete Overview of Fields in Odoo 19, refer to our blog A Complete Overview of Fields in Odoo 19.


Frequently Asked Questions

Do these fields create database-level foreign keys?

No, neither Reference nor Many2oneReference enforces database-level foreign key constraints.

Are these fields slower than Many2one?

Yes, they can be slightly slower because the relationship is resolved dynamically rather than through direct database constraints.

Can these fields be used in reports?

Yes, but additional handling may be required because the related model is not fixed.

Should I replace all Many2one fields with these?

No. Many2one should still be used for fixed relationships. Reference and Many2oneReference should only be used when flexibility is required.

If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, KINFRA Techno Park
Kakkanchery, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message