Using default_get() — Why Do Readonly Field Values Disappear After Saving in Odoo?

When customizing forms in Odoo, it’s quite common to use default_get() to automatically fill certain fields when creating a new record. In most situations, this works exactly as expected.

But things can get confusing when that field is marked as readonly.

You might have seen this happen:

  • You define a field as readonly
  • You populate its value using default_get()
  • The value appears correctly when the form opens
  • You save the record
  • And suddenly… the value disappears

At first glance, this feels like a bug. But in reality, it’s just how Odoo’s web client is designed to work.

What’s Actually Happening Behind the Scenes?

When you open a new form view, Odoo calls the default_get() method to populate default values. These values are shown in the user interface — even for readonly fields.

However, during the save operation, the web client only sends back values that are considered editable or modified by the user.

Since readonly fields:

  • Cannot be edited
  • Are not changed by user interaction

They are treated as unchanged values, and therefore:

👉 They are not included in the data sent to the server when the record is saved.

As a result, the ORM never receives those values — and they are not stored in the database.

That’s why the value disappears after saving.

Reproducing the Issue

Python Model

from odoo import models, fields, api


class StudentRegistration(models.Model):

_name = "student.registration"


name = fields.Char(string="Student Name")

reference_code = fields.Char(string="Reference Code", readonly=True)


@api.model

def default_get(self, fields_list):

res = super().default_get(fields_list)

res['reference_code'] = "REF-001"

return res

XML View

<field name="reference_code" readonly="1"/>

Now:

  • Open the form
  • You’ll see the Reference Code is filled
  • Click Save
  • The value disappears

This happens because the readonly field was never sent back to the server during record creation.

UI-Level Fix: Using force_save="1"

If you want the readonly value from the form to be saved, you can instruct the web client to include it during submission by adding:

<field name="reference_code" readonly="1" force_save="1"/>

With this:

  • The value is included in the save request
  • The ORM receives it
  • The value is stored correctly
  • It remains visible after saving

This approach is useful when the value is mainly related to UI behavior and is expected to be created from the form itself.

Recommended Backend Approach: Assign Value in create()

If the value is important for business logic — like an internal reference, identifier, or workflow dependency — it’s better to assign it at the ORM level instead of relying on the form view.

Here’s how you can do that:

@api.model

def create(self, vals):

if not vals.get('reference_code'):

vals['reference_code'] = "REF-001"

return super().create(vals)

This ensures the value is stored:

  • Even if the record is created via API
  • During CSV import
  • From automated cron jobs
  • Through external integrations

In other words, it works regardless of how the record is created — not just from the form view.

When Should You Use What?

Use force_save when:

  • The field is readonly in the UI
  • The value is assigned through the form
  • The value is display-oriented

Use create() override when:

  • The value is business-critical
  • It must always be stored
  • The record may be created through automation or integrations


When a readonly field is populated using default_get(), it may disappear after saving because readonly fields are not included in the form submission sent to the server.

This is expected behavior in Odoo — not a bug.

To make sure the value persists:

  • Use force_save="1" for form-level persistence
  • Or assign the value in create() for backend reliability

Understanding this small detail can save a lot of debugging time when developing custom Odoo modules.

Share this post
Tags
Archive
One Missing super() Can Break Odoo — Here’s How to Override Safely