यह लेख वर्तमान में केवल अंग्रेज़ी में उपलब्ध है। अनुवाद जल्द आ रहा है।
Your Odoo tree (or list) view declares fields as readonly, but users can still click in and edit them. Or the inverse — fields that should be editable are stubbornly readonly. Sometimes the row appears uneditable, the user opens its form view, and edits go through fine. The UI is lying about its own state. This bites Odoo 17.0/18.0/19.0 with the same root causes.
Quick Fix
Decide what you want and set both the view and the field consistently:
<!-- For an editable tree view where SOME fields are readonly -->
<list editable="bottom">
<field name="name"/> <!-- editable -->
<field name="price" readonly="state == 'done'"/> <!-- conditional readonly -->
<field name="state" readonly="1"/> <!-- always readonly -->
</list>
If the entire list should be view-only, omit editable=:
<list> <!-- no editable= attribute → list is view-only, double-click opens form -->
<field name="name"/>
<field name="price"/>
<field name="state"/>
</list>
Why This Happens
Odoo's list views have two orthogonal axes: the list is editable inline (or not), and each field is editable (or not). The combination:
<list editable="top">+<field name="x"/>→ field is editable inline.<list editable="top">+<field name="x" readonly="1"/>→ field is uneditable inline, but the form view's setting still applies in form mode.<list>(no editable) +<field name="x"/>→ list is not inline-editable; double-click goes to form view; form view's readonly applies there.
The four common bugs:
readonly="1"on the field buteditable="bottom"on the list — the field is inline-readonly but the row still looks "active" because the list is editable mode. Confusing UX.readonlyattribute is a Python expression that evaluates wrong.readonly="state == 'done'"does not match becausestateis'sale'not'done'— field stays editable.- ACL allows write but the field's
readonly=attribute does not. Tree shows the field as editable to admins but readonly to others — mismatchedgroups=. - Studio customization that set readonly via UI overrides the module XML for some users.
Step-by-Step Diagnosis
1. Check the rendered arch. Developer Mode → "Edit ListView" → "Show updated arch". Read the composed XML.
2. Verify the field's readonly:
SELECT name, readonly FROM ir_model_fields
WHERE model = 'sale.order' AND name = 'amount_total';
If readonly=true here, no view can make it editable — the field itself is locked.
3. Test the readonly expression at runtime.
order = env['sale.order'].browse(14)
# In a shell, the readonly expression's variables come from the record's fields
print(order.state) # is this what the readonly= expects?
4. Check ACL.
env['sale.order'].with_user(user_id).check_field_access_rights('write', ['amount_total'])
If the user does not have write access, the field is readonly regardless of view.
5. Check Studio overrides.
SELECT id, name, arch_db FROM ir_ui_view
WHERE model = 'sale.order' AND name LIKE 'studio%';
Studio adds inheritance views; one of them may force readonly.
Permanent Fix
Pick the right combination:
<!-- Pattern 1: View-only list (most common) -->
<list>
<field name="name"/>
<field name="price"/>
<field name="state"/>
</list>
<!-- Pattern 2: Inline-editable list, all fields editable -->
<list editable="bottom">
<field name="name"/>
<field name="price"/>
</list>
<!-- Pattern 3: Inline-editable list, some fields read-only -->
<list editable="bottom">
<field name="name"/>
<field name="price" readonly="state == 'done'"/>
<field name="state" readonly="1"/>
</list>
For dynamic readonly based on record state, use the new attribute syntax (Odoo 17.0+):
<field name="amount_total" readonly="state in ('done', 'cancel')"/>
Important: this is a Python expression evaluated against the record's field values. Misspell a field name and the expression silently evaluates False, leaving the field always editable.
For Odoo 19.0+, attrs and states are removed:
<!-- WRONG — will not work in Odoo 19.0 -->
<field name="amount_total" attrs="{'readonly': [('state', 'in', ['done', 'cancel'])]}"/>
<!-- RIGHT — Odoo 17.0+ syntax -->
<field name="amount_total" readonly="state in ('done', 'cancel')"/>
Migrate every attrs= to the direct attribute form before upgrading to 19.0. ECOSIRE's Odoo migration team ships an attrs-to-attribute conversion for every customer upgrade.
For ACL-based readonly, the cleanest pattern is field-level groups:
amount_total = fields.Monetary(
'Total',
groups='sales_team.group_sale_manager', # readonly for everyone else
)
Better still, separate display and write rights at the model level via ir.model.access so the entire UX is consistent.
How to Prevent It
- One source of truth per field. Decide whether the field is mutable based on state, ACL, or the field declaration itself. Mixing all three layers is what creates "readonly but editable" confusion.
- Migrate attrs to attribute syntax now. Even on Odoo 17.0/18.0,
attrs=is deprecated. Updating early avoids a panicked migration. - Snapshot test edit behaviour. A Playwright test that opens the list as different users, attempts an edit, and asserts the success/failure case catches readonly drift.
- Use
force_save="1"carefully. This attribute makes a readonly field writable in form save, which has surprising semantics. Reserve for special cases and document why. - Lint dynamic readonly expressions. A CI check that parses every
readonly="..."and validates field names against the model catches typos before deploy. - Unify list and form readonly logic. If amount_total is readonly when state=done, both list and form should reflect this. Inconsistency creates "list says readonly, form lets me edit" bug reports.
Related Errors
- attrs/states deprecated in Odoo 19 — direct cause of readonly issues after 19.0 upgrade.
- Form view renders blank — sibling view bug.
- Search view domain ignored — same family of UI-state-vs-actual-state mismatches.
- AccessError on res.users — ACL-related readonly enforcement.
Frequently Asked Questions
Can a field be readonly in list but editable in form?
Yes. Set readonly="1" on the list <field> but leave it unset on the form <field>. The two views have independent attribute sets even though they share the same field declaration on the model.
Why does my readonly expression work for some users but not others?
Almost always because the variables in the expression are not loaded for some users. If the expression references state, the form must declare <field name="state"/> (even invisibly) so the value is available client-side. ACL can also strip the field, in which case the expression evaluates against an undefined value.
What is the difference between readonly="1" and readonly="True"?
In Odoo 17.0+ XML, "1" and "True" are equivalent. Some older code used 'True' with quotes. Stick to "1" for unconditional readonly and unquoted Python expressions for dynamic.
Can I make a field conditionally required AND conditionally readonly?
Yes. Both required="..." and readonly="..." accept Python expressions. Just be careful that the combination is sane — required + readonly together means "cannot save until set, cannot set" which traps users. Add a button or onchange to populate the field if you make it both.
What is column_invisible and when do I need it?
column_invisible hides a list view column (saving render cost) without affecting the underlying record. Useful for fields you need server-side but not displayed:
<field name="currency_id" column_invisible="1"/> <!-- hide column entirely -->
<field name="amount_total" widget="monetary"/> <!-- needs currency_id loaded -->
The currency_id is fetched (so the monetary widget works) but its column does not render.
How do I prevent edits via force_save="1"?
force_save="1" lets a readonly field still be saved if the form has changes elsewhere. Use it sparingly — it is a security relaxation. The right pattern is to leave the field readonly without force_save and provide an explicit button or wizard to update it.
Need help with a tricky Odoo error? ECOSIRE's Odoo experts have shipped 215+ modules — get expert help.
लेखक
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
ECOSIRE
Odoo ERP के साथ अपना व्यवसाय बदलें
आपके संचालन को सुव्यवस्थित करने के लिए विशेषज्ञ ओडू कार्यान्वयन, अनुकूलन और समर्थन।
संबंधित लेख
How to Add a Custom Button to an Odoo Form View (2026)
Add custom action buttons to Odoo 19 form views: Python action method, view inheritance, conditional visibility, confirmation dialogs. Production-tested.
How to Add a Custom Field in Odoo Without Studio (2026)
Add custom fields via custom module in Odoo 19: model inheritance, view extension, computed fields, store/non-store decisions. Code-first, version-controlled.
How to Add a Custom Report in Odoo Using External Layout
Build a branded PDF report in Odoo 19 using web.external_layout: QWeb template, paperformat, action binding. With print logo + footer overrides.