Readonly fields are one of those features in Odoo that seem straightforward at first but play a much bigger role than most users expect.
Whether you are a business user wondering why certain fields are greyed out, or a developer looking to control field behavior in your Odoo customization, this guide covers everything you need to know.
Understanding how readonly fields work is key to building reliable workflows, protecting data integrity, and delivering a smoother experience for your team.
This Odoo field tutorial walks through both the business and technical sides of readonly, so whether you are configuring Odoo or building on top of it, you will find what you need here.
What Is the Readonly Field in Odoo
A readonly field in Odoo is a field that displays a value but cannot be edited directly by the user through the interface. The data is visible, but the input is locked.
In the form view, readonly fields typically appear as plain text rather than interactive input boxes. Depending on the Odoo theme, they may look slightly greyed out or simply flat compared to editable fields.
Within the Odoo data model, readonly behavior can be applied at two distinct levels:
- At the field level (Python/ORM): the field is always readonly across all views and contexts
- At the view level (XML): the field is readonly in a specific view or under specific conditions
This distinction is important. A field marked as readonly at the ORM level cannot be edited through any user interface. A field marked readonly at the view level is protected in that particular context but may still be writable in other views or through server-side code.
Readonly is not a field type by itself. It is an attribute that can be applied to any of the standard Odoo field types: Char, Integer, Float, Many2one, Date, and others. This is a core part of the Odoo framework for controlling how fields behave at runtime.
How the Readonly Field Works
To understand how readonly fields behave, it helps to look at both sides: the Odoo ORM (Python) and the view layer (XML).
Readonly at the ORM Level
In the Odoo ORM, a field can be declared as permanently readonly directly in the Python model. This is most common for computed fields that derive their value from other data. The field definition includes readonly=True as a parameter, and Odoo will never allow the user to edit it through the UI.
This level of readonly is part of the Odoo Python fields API and is documented in the official Odoo developer guide. It applies globally, regardless of which view is being used.
State-Based Readonly
One of the most common patterns in Odoo development is making a field readonly based on the current state of a document. This is how standard modules like Sales, Purchases, and Accounting lock their data once a document moves past the draft stage.
In Odoo 16 and earlier versions, this was done using the attrs attribute in view XML, combining a domain condition with the field element. In Odoo 17 and later, the syntax is more concise and written directly as an inline expression on the field element.
Both approaches achieve the same result: the field is editable while the document is in draft, and becomes locked once it progresses through the workflow. This is a fundamental concept in any Odoo technical tutorial covering field configuration.
Computed Fields and Readonly
Odoo computed fields are readonly by default. When you define a field with a compute method, Odoo assumes it should not be edited directly because its value is derived automatically from other fields.
If you want a computed field to also be stored, you set both the compute parameter and store=True. These stored Odoo database fields are a common pattern for performance optimization, since they can be used in search filters and sorted efficiently at the database level without recalculating values on the fly.
Making a Computed Field Writable
If you need a computed field to also accept manual input, you can define an inverse method alongside it. The inverse method tells Odoo what to do when a user writes a value to the computed field. Without an inverse, the field remains readonly by default. This is part of the more advanced Odoo ORM field types API and is covered in depth in the Odoo developer guide.
Business Use Cases
Readonly fields appear throughout every Odoo module. Here are five practical examples from real business workflows.
1. CRM: Locking Won and Lost Opportunity Data
In the CRM module, the expected revenue and closing date are editable while a lead is being worked. Once an opportunity is marked as Won or Lost, these fields are set to readonly to preserve an accurate record of what was closed and at what value.
This prevents anyone from going back and adjusting figures after the fact, which would distort sales reports and pipeline analytics.
2. Sales: Protecting Confirmed Order Lines
When a sales order moves from Draft to Confirmed, the order lines become readonly. Users can no longer change the product, quantity, or price after the customer has received a confirmation.
If changes are genuinely needed, the order must be explicitly reset to draft, which creates an audit trail and makes the correction intentional rather than accidental.
3. Inventory: Validated Stock Move Quantities
In warehouse operations, once a delivery or receipt is validated, the quantities done are locked. This protects the integrity of stock valuation and ensures the records match what physically moved through the warehouse.
Editable quantities after validation could silently corrupt inventory levels across multiple locations.
4. Accounting: Posted Journal Entry Lines
In accounting, once a journal entry is posted, all its lines become readonly. This is both a legal requirement in many countries and a core principle of double-entry bookkeeping.
Allowing edits after posting would compromise the reliability of financial statements and create serious compliance risks.
5. Manufacturing: Completed Work Order Data
In the Manufacturing module, once a work order is marked as finished, the actual duration and quantities produced are set to readonly. This preserves accurate production records that feed into cost analysis and performance tracking.
Creating or Customizing a Readonly Field
There are two main paths to configure readonly fields in Odoo: using Odoo Studio for a no-code approach, or writing Python and XML directly for full technical control.
Using Odoo Studio
Odoo Studio fields make it easy to add or modify readonly behavior without writing any code. To configure a field as readonly using Studio:
- Open Odoo Studio from the main menu (the pencil icon)
- Navigate to the form view where you want to configure the field
- Click on the field you want to modify
- In the right-side properties panel, toggle the "Readonly" option
- Save and close Studio
Studio also allows you to set conditional readonly behavior using domain expressions. For example, you can make a field readonly only when a status field equals a specific value, without writing a single line of code.
The create fields Odoo Studio approach is the right choice for consultants and administrators who need to enforce data rules quickly and safely. Changes made through Studio are stored in the database and will not be overwritten by module upgrades.
Using Python for Technical Customization
For developers building custom Odoo modules, the readonly attribute is set directly on the field definition in the Python model. This is standard Odoo Python fields usage and is covered in every Odoo developer guide.
You can set readonly=True as a static parameter on any field type, making it permanently non-editable. For more flexible control, the states parameter allows you to define in which document states the field should be writable versus readonly.
This approach is particularly useful when you are adding custom fields to existing Odoo models as part of an Odoo customization project. It keeps the field logic close to the data model rather than scattered across multiple view files.
Using XML View Attributes
For view-level readonly behavior, you add the readonly attribute directly to the field element in your view XML. This is part of the standard Odoo development workflow for any technical customization.
The advantage of view-level readonly is flexibility: the same field can behave differently in different views, or under different conditions, without changing the underlying field definition. This is often the preferred approach when you need to add restrictions to existing standard fields without modifying their Python definition.
In Odoo 17, the inline expression syntax for readonly conditions is cleaner and more readable than the older attrs dictionary syntax used in earlier versions. Both approaches are valid depending on which Odoo version you are running.
Best Practices
Using readonly fields well comes down to applying them at the right level, for the right reason. Here are the most important guidelines from an Odoo consulting perspective.
1. Prefer View-Level Readonly When the Context Varies
If a field needs to be readonly only in certain document states or in specific views, apply the readonly at the view level rather than the model level. This keeps your Odoo data model flexible and allows backend processes or API integrations to still write to the field when needed.
2. Align Readonly Conditions with the Document Lifecycle
Your readonly conditions should match the natural flow of your documents. Fields should lock when the document reaches a state where further edits would cause problems. This creates a predictable and intuitive experience for users, which is one of the hallmarks of a well-implemented Odoo customization.
3. Test Across User Roles
Readonly behavior can interact with access rights in unexpected ways. Always test your configuration as both a standard user and an administrator to verify that the field behaves correctly for each role. What looks readonly to one user group might still be editable for another depending on their profile.
4. Combine Readonly with Required Where It Makes Sense
In multi-stage forms, a field might be required in draft but readonly in later states. You can combine both attributes in your view XML to enforce this pattern cleanly. This is common for fields like delivery dates or reference numbers that must be filled in before a document is confirmed.
5. Document Your Readonly Logic
In custom Odoo development, especially on complex data models, always add a comment explaining why a field is readonly. Future developers maintaining the code need to understand the business reason behind the restriction, not just the technical implementation.
6. Use Studio Fields for Quick, Upgrade-Safe Changes
For straightforward use cases, Odoo Studio fields offer a fast and upgrade-safe way to add readonly behavior. Reserve Python customization for cases where Studio cannot deliver the required logic, such as complex cross-field conditions or integration with custom computed fields.
Common Pitfalls
Even experienced Odoo users and developers run into the same issues with readonly fields. Here are the ones worth knowing about before they catch you off guard.
Confusing View-Level Readonly with a Security Boundary
A field set as readonly in a view does not prevent updates through the XML-RPC API, ORM write calls in Python, or server actions. View-level readonly is a UI restriction, not a security control. If you genuinely need to prevent all writes to a field, you need to enforce that at the ORM level or through access control rules, not just in the view.
Making Fields Permanently Readonly When Conditional Would Be Better
It is tempting to lock a field completely when you want to protect it. But if users legitimately need to edit it in certain situations, such as when resetting a document to draft, a permanent ORM-level readonly will block them entirely, including any correction workflows. Always think through the full lifecycle before choosing permanent over conditional.
Forgetting About Onchange Methods
If a readonly field is also referenced in an onchange method, that method can still attempt to assign a value to it. This can produce confusing behavior where the field appears to update during user interaction but then reverts or triggers an error. Make sure your onchange logic accounts for readonly fields.
Not Applying Readonly Consistently Across All Views
A field marked as readonly in the form view might still be editable in the list view or kanban view if those views do not include the same restriction. Always check that your readonly configuration is applied consistently across every view where the field appears.
Side Effects When Inheriting Standard Models
When inheriting from a standard Odoo model and adding readonly=True to an existing field, this change affects all views that show that field, including standard ones. Make sure this is intentional and that it will not break standard Odoo behavior or conflict with other customizations on the same model.
Conclusion
Readonly fields are a fundamental tool in Odoo for guiding users through workflows, protecting data integrity, and enforcing business rules without relying on training alone.
The key is knowing when to apply readonly at the view level versus the model level, and making sure the conditions align with how your team actually works. A well-configured Odoo data model always makes thoughtful use of readonly fields at the right moments in the document lifecycle.
Whether you configure them through Odoo Studio for a no-code approach or define them directly in Python and XML as part of a broader Odoo development project, the logic behind readonly fields remains consistent: show the data, but protect it from unintended changes.
They may not be the most discussed topic in Odoo customization, but they are quietly one of the most impactful.
At Dasolo, we help companies implement, customize and optimize Odoo across all modules and industries. If you need help configuring fields, designing reliable workflows, or improving your Odoo data model, our team is ready to support you. Get in touch and tell us about your project.