Enable Dark Mode!
how-reference-and-many2onereference-fields-work-in-odoo-18.jpg
By: Swaraj R

How Reference and Many2oneReference Fields Work in Odoo 18

Technical Odoo 18 Odoo Enterprises Odoo Community

In the case of relationships in Odoo, it’s not always the case that the connection between two models is static. Even though field types like Many2one fit perfectly for situations where you need to associate two models, the truth is that real-life situations may vary from one to another.

At times, it will be necessary to establish associations between a particular field and many record types according to certain criteria. For these kinds of cases, Odoo offers the Reference and Many2OneReference fields. Let’s look at them in more detail here in this post.

Where to Place the Code (Very Important)

Your custom module should look like this:

your_module_name

+-- __init__.py
+-- __manifest__.py
+-- models/
¦   +-- __init__.py
¦   +-- personal_details.py   <-- MODEL CODE HERE
+-- views/
¦   +-- personal_details_views.xml   <-- VIEW CODE HERE
reference_doc = fields.Reference(
   selection=[
       ('sale.order', 'Sales Order'),
       ('account.move', 'Invoice'),
       ('stock.picking', 'Delivery Order'),
   ],
   string="Related Document",
   help="Link this ticket to a business document."
)

Reference Fields in Odoo 18

The Reference field allows the user to establish relationships between a record and several models in just one field.

No need to declare several fields; only define the list of acceptable models, and the user will select one while working.

How It Works

Working with a Reference field in the frontend:

  • Firstly, the user chooses the model (Sales Order, Invoice etc.)
  • Then the user selects a specific record in this model.
  • Data storage in Odoo is done internally by the database.

Example value stored:

sale.order, 24

Explanation:

  • Model > sale.order
  • Record ID > 24

Advantages

  • Fewer field requirements
  • Flexible to use
  • Good for general references (logs, documents, activities etc.)

Important Notes

  • No foreign key relationship established
  • selection_add usage possible
  • Slightly slow as compared to Many2one because it is dynamic, Control what models are allowed via the selection

Many2oneReference Fields in Odoo 18

The Many2oneReference field is yet another type of field used to create dynamic relationships. Unlike the previous method, the Many2oneReference field separates the whole idea into two parts:

  1. A Char field > stores the model name
  2. A Many2oneReference field > stores the record ID

How It Works

  • The user enters the model name (for example, sale.order), Accordingly, the field of record changes itself depending on the value provided
  • Finally, the user can select the required record benefits
  • More control over the process of creating dynamic relationships
  • Separates the model from the record
  • Used when developing a configurable system

This makes the field behave dynamically depending on the model value.

Why Use It

  • Gives more control over dynamic relationships
  • Cleaner separation of model and record
  • Useful in configurable systems
model_name = fields.Char(
   string="Model Name",
   help="Technical model name (e.g., sale.order, purchase.order)"
)
record_id = fields.Many2oneReference(
   string="Record",
   model_field='model_name',
   help="Select record dynamically based on model."
)

Key Differences

FeatureReferenceMany2oneReference
StorageSingle fieldTwo fields
Model controlPredefined listDynamic
FlexibilityMediumHigh
SimplicityEasierSlightly complex

When Should You Use These Fields?

Use Reference Field When:

  • You know the possible models in advance
  • You want a simple dropdown-based selection

Example:

  • Linking a record to Sale Order / Invoice / Delivery

Use Many2oneReference When:

  • The model is not fixed
  • The model should be dynamic or configurable

Example:

  • Workflow engines
  • Approval systems
  • Generic automation rules

Complete Model Code (Odoo 18)

Create a file named personal_details.py inside the models directory.

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

class PersonalDetails(models.Model):
   _name = 'personal.details'
   _description = 'Personal Details'
   name = fields.Char(
       string='Name',
       required=True,
       help="Enter the full name of the person."
   )
   age = fields.Integer(
       string='Age',
       help="Enter the age."
   )
   gender = fields.Selection(
       [
           ('male', 'Male'),
           ('female', 'Female'),
           ('other', 'Other')
       ],
       string='Gender'
   )
   email = fields.Char(string='Email')
   phone = fields.Char(string='Phone')
   # Reference Field (Base)
   reference = fields.Reference(
       selection=[
           ('res.partner', 'Partner'),
           ('sale.order', 'Sales Order'),
           ('purchase.order', 'Purchase Order'),
       ],
       string="Related Document"
   )
   # Another Reference Example
   document_reference = fields.Reference(
       selection=[
           ('res.partner', 'Partner'),
           ('res.users', 'User'),
           ('product.product', 'Product')
       ],
       string="Document Reference"
   )
   # Dynamic Reference Fields
   m2o_reference_model = fields.Char(
       string='Reference Model',
       help="Technical model name (example: sale.order)"
   )
   m2o_reference_id = fields.Many2oneReference(
       string='Related Record',
       model_field='m2o_reference_model'
   )
   status = fields.Selection(
       [
           ('draft', 'Draft'),
           ('confirmed', 'Confirmed'),
           ('done', 'Done')
       ],
       default='draft',
       string="Status"
   )
   notes = fields.Text(string="Notes")
   active = fields.Boolean(default=True)

View Definition

Create a file named personal_details_views.xml inside the views directory.

<?xml version="1.0" encoding="utf-8"?>
<odoo>
       <!-- 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"/>
                   <field name="status"/>
               </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"/>
                               <field name="status"/>
                           </group>
                           <group>
                               <field name="email"/>
                               <field name="phone"/>
                               <field name="active"/>
                           </group>
                       </group>
                       <notebook>
                           <!-- Reference Fields -->
                           <page string="Reference">
                               <group>
                                   <field name="reference"/>
                                   <field name="document_reference"/>
                               </group>
                           </page>
                           <!-- Dynamic Reference -->
                           <page string="Dynamic Reference">
                               <group>
                                   <field name="m2o_reference_model"
                                          placeholder="example: sale.order"/>
                                   <field name="m2o_reference_id"/>
                               </group>
                           </page>
                           <!-- Notes -->
                           <page string="Notes">
                               <field name="notes"/>
                           </page>
                       </notebook>
                   </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>
       </record>
       <!-- Menu -->
       <menuitem id="menu_personal_details_root"
                 name="Personal Details"
                 sequence="10"/>
       <menuitem id="menu_personal_details"
                 name="Records"
                 parent="menu_personal_details_root"
                 action="action_personal_details"
                 sequence="10"/>
</odoo>

Fields Reference and Many2oneReference prove their usefulness when some level of flexibility is needed in data modeling.

The approach allows for not hardcoding fields and building more robust and reusable code that could adapt to any circumstances.

Use Reference relations when you know the set of models in advance.

Apply Many2oneReference relations where the model should be determined dynamically.

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


Frequently Asked Questions

What is the key difference between Reference and Many2oneReference?

Reference saves the model and record on one field, while Many2oneReference saves them using two fields model name and record.

Does the use of these fields build any relation within the database?

Not exactly, because these fields don't build foreign keys, unlike Many2one; they work dynamically inside the application itself.

Are these fields slower than Many2one fields?

Yes, to some extent, due to the dynamic nature of resolving a model.

Could these fields be used in reports as well?

Yes, however, some more work will be required related to working with the target model.

Should I modify all my Many2one relations?

No. Apply Many2one relations where the relation is unambiguous, and apply Reference or Many2oneReference relations where 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
Kakkancherry, 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