Understanding the Rare ORM Method name_get() in Odoo 19

 


 

When working with Odoo development, most developers frequently use ORM methods like create(), write(), search(), and unlink(). However, Odoo also provides several lesser-known ORM methods that quietly power many UI behaviors behind the scenes.

One such important method is name_get().

Even though many developers rarely touch it, this method becomes extremely important when dropdown labels, breadcrumbs, chatter references, or Many2one fields start displaying incorrect or confusing values.


What is name_get() in Odoo?

The name_get() method defines how a record should appear as a readable label inside the Odoo interface.

Odoo uses it in places like:

  • Many2one dropdowns

  • Breadcrumbs

  • Chatter mentions

  • Smart buttons

  • Search popups

  • RPC calls and backend references

The method returns a list of tuples in this format:

[(record_id, display_name)]

Example:

[(1, 'Azure Interior'),
 (2, 'Deco Addict'),
 (3, 'Agrolait')]

Default Behavior of name_get()

If you do not override name_get(), Odoo automatically uses the field defined in _rec_name.

By default, _rec_name is usually the name field.

Internally, Odoo behaves roughly like this:

def name_get(self):
    result = []
    name_field = self._rec_name or 'name'

    for record in self:
        result.append((record.id, record[name_field] or ''))

    return result

So if your model only contains a name field, the dropdown simply shows that value.

While this works for simple cases, real business applications often require more descriptive labels.


Major Change in Odoo 19 – display_name Becomes Important

Starting from Odoo 17 and fully adopted in Odoo 19, the web client no longer directly relies on name_get() for Many2one dropdown labels.

Instead, Odoo now primarily uses the display_name field.

This is a very important architectural change.

What This Means

Simply overriding name_get() is no longer enough in Odoo 19.

To properly customize record labels, you should:

  • Create a computed display_name field

  • Use @api.depends() correctly

  • Keep name_get() for backward compatibility

This ensures compatibility with:

  • Older RPC integrations

  • Reports

  • Shell scripts

  • Legacy custom modules


Recommended Pattern in Odoo 19

from odoo import models, fields, api

class HospitalWard(models.Model):
    _name = 'hospital.ward'
    _description = 'Hospital Ward'
    _rec_name = 'name'

    name = fields.Char(required=True)
    code = fields.Char()
    capacity = fields.Integer()

    display_name = fields.Char(
        compute='_compute_display_name',
        store=False,
    )

    @api.depends('name', 'code', 'capacity')
    def _compute_display_name(self):
        for record in self:
            name = record.name or ''

            if record.code:
                name = f'[{record.code}] {name}'

            if record.capacity:
                name = f'{name} (Cap: {record.capacity})'

            record.display_name = name

    # Backward compatibility
    def name_get(self):
        return [
            (record.id, record.display_name)
            for record in self
        ]

Example Output

Instead of showing:

Cardiology
Neurology

the dropdown will now display:

[W-01] Cardiology (Cap: 20)
[W-02] Neurology (Cap: 15)

This greatly improves usability, especially in large ERP systems where similar names may exist across departments or branches.


Why display_name is Better in Odoo 19

Using display_name provides several advantages:

  • Reactive UI updates

  • Better frontend performance

  • Cleaner web client integration

  • Improved consistency across views

  • Modern Odoo architecture compatibility

In Odoo 19, display_name is effectively the primary display mechanism.


name_get() and name_search() Should Always Work Together

A common mistake developers make is customizing the label using name_get() but forgetting to update search behavior.

For example:

If the dropdown label is:

[PAT-001] John Smith

but search only checks the name field, searching for PAT-001 will fail.

That is why name_search() should usually be overridden together with name_get().


Proper name_search() Example

@api.model
def name_search(
    self,
    name='',
    domain=None,
    operator='ilike',
    limit=100
):
    domain = domain or []

    if name:
        records = self.search(
            ['|',
             ('patient_code', operator, name),
             ('name', operator, name)] + domain,
            limit=limit
        )

        return records.name_get()

    return super().name_search(
        name=name,
        domain=domain,
        operator=operator,
        limit=limit
    )

Important Note for Odoo 19

In Odoo 19:

domain

is used instead of:

args

Using args may raise a TypeError in newer versions.


Final Thoughts

For many years, name_get() was the standard approach for customizing record labels in Odoo.

However, Odoo 19 changes the game by shifting most UI rendering responsibility to display_name.

The modern best practice is:

  • Use computed display_name

  • Add proper @api.depends

  • Keep name_get() for compatibility

  • Pair it with name_search()

These small improvements make your custom modules feel much more polished, user-friendly, and production-ready.

Understanding these lesser-known ORM methods is what separates basic Odoo development from advanced enterprise-level implementation.

Comments