Skip to Content

Attrs in Odoo: Old vs New Syntax (Odoo 15–19 Guide)

Author
SerpentCS
March 2010 - 7 min read
Share
Blog Feature Image

Odoo 17 introduced a significant shift in how developers handle dynamic field properties in views, moving away from the classic attrs dictionary to more intuitive inline expressions. This guide breaks down both the legacy syntax for Odoo 16 and earlier and the modern approach used in Odoo 17, 18, and 19.

Which Syntax Should You Use?

Your Odoo version determines your coding style:

  • Odoo 16 and Earlier: Use the attrs attribute with dictionary-based domains.

  • Odoo 17, 18, and 19: Use direct inline expressions on attributes like readonly, invisible, and required.

Part 1: The Classic attrs Attribute (Odoo ≤16)

In older versions, attrs is a dictionary used to modify field properties (like making them mandatory, read-only, or hidden) based on the value of other fields. This logic is processed directly in the browser without needing a server request.

General Syntax: attrs="{'attribute': [domain_condition]}"

Example Model Context: Imagine a student record with a state field and a school_id.

1. Readonly

To make the school_id field read-only once a student record is confirmed: <field name="school_id" attrs="{'readonly': [('state', '=', 'confirm')]}"/>



2. Invisible

To hide the school_code field until a school is actually selected: <field name="school_code" attrs="{'invisible': [('school_id', '=', False)]}"/>


We can see ‘school’ information is not available so, school code information is not
shows as per attrs ‘school code’ information is hide.

 


After select or fillup the School information we can see the school code
information on Student form view as per applied attrs on School code field.

3. Required

To make a phone number mandatory only when a school is selected: <field name="school_phone_no" attrs="{'required': [('school_id', '!=', False)]}"/>


 4. Logical Operators (AND/OR)

  • OR: Use the '|' symbol. attrs="{'required': ['|', ('school_id', '!=', False), ('school_code', '!=', False)]}"

  • AND: Odoo uses "and" by default if no symbol is provided. attrs="{'required': [('school_id', '!=', False), ('school_code', '!=', False)]}"


Using the same Student Model context as the legacy examples, here is how you implement these dynamic behaviors in the modern syntax:

Part 2: Modern Inline Attribute Syntax (Odoo 17, 18, & 19)

1. Readonly

To make a field like school_id non-editable once a record is confirmed, you use a direct comparison. The syntax is shorter and more readable because it follows standard Python logic.

  • Expression: readonly="state == 'confirm'"

  • XML Example: <field name="school_id" readonly="state == 'confirm'"/>

2. Invisible

Hiding a field until a specific condition is met is now done using the invisible attribute directly. For instance, to hide the school_code until a school is actually selected, you can use the not operator.

  • Expression: invisible="not school_id"

  • XML Example: <field name="school_code" invisible="not school_id"/>

3. Required

Making a field mandatory conditionally is equally streamlined. For example, to require a school_phone_no only when a school_id is present, you simply pass the field name as a boolean condition.

  • Expression: required="school_id"

  • XML Example: <field name="school_phone_no" required="school_id"/>

4. Logical Operators (AND/OR)

One of the biggest improvements in Odoo 17+ is the removal of the complex prefix notation (like '|' or '&') in favor of standard Python logical operators.

  • OR Condition: Use the or keyword to apply a property if either condition is true.

    • XML Example: <field name="school_phone_no" required="school_id or school_code"/>

  • AND Condition: Use the and keyword when both conditions must be true.

    • XML Example: <field name="school_phone_no" required="school_id and school_code"/>

Key Takeaway for Modern Versions: The new syntax is designed to be shorter, more readable, and more intuitive for anyone familiar with Python, as it eliminates the need for the attrs dictionary and list-based domain wrappers


Key Changes:

  • No dictionary or domain wrappers are required.

  • Conditions are written as plain Python-like expressions.

Side-by-Side Comparison

Behavior

Legacy Odoo ≤16 (attrs)

Modern Odoo 17+ (Inline)

Readonly

attrs="{'readonly': [('state','=','confirm')]}"

readonly="state == 'confirm'"

Invisible

attrs="{'invisible': [('school_id','=',False)]}"

invisible="not school_id"

Required

attrs="{'required': [('school_id','!=',False)]}"

required="school_id"

Multiple (OR)

[‘|’, (cond1), (cond2)]

cond1 or cond2

Multiple (AND)

[(cond1), (cond2)]

cond1 and cond2


Migration Tips for Developers

If you are upgrading a module from Odoo 16 to Odoo 17 or later, follow these best practices:

  • Search and Replace: Find every occurrence of attrs= in your XML views and convert the domain into a boolean expression.

  • Verify Logic: While Odoo provides some migration utility scripts, manual review is critical for complex conditions (3+ logic gates) where bugs often occur.

  • No Mixing: You cannot use both old and new syntax in the same view; doing so will cause a parsing error.

  • Check states: Remember that the states attribute is also deprecated; replace it with inline invisible or readonly conditions.

By adopting the new inline syntax, you'll find your Odoo views are easier to maintain and much closer to standard Python logic.


FAQs

No. attrs was fully removed in Odoo 17. Views using it will raise a validation error on module load.

No — within a single view, you must use the syntax matching your Odoo version. Mixed syntax will cause a parsing error.

Yes, states was deprecated alongside attrs starting Odoo 17. Use inline conditions instead.

Odoo provides upgrade utility scripts, but manual review is strongly recommended for views with multiple chained conditions.

Yes, this is a core ORM/view-engine change and applies identically to both editions.


Do you need help with moving your views to a new version?

If you are changing from Odoo 16 or an earlier version and you need to update your custom modules to the way of writing code our team that works on Odoo can check and move your views without causing any problems with the way things already work.

Now we can handle Odoo views for versions 15, through 19.




Connect with us & Explore More about SerpentCS

Web www.serpentcs.com
Solutions www.serpentcs.in
Apps https://bit.ly/SCS_AppsStore
YouTube https://bit.ly/SCS_YTChannel
LinkedIn https://bit.ly/SCS_LinkedIN
Email contact@serpentcs.com

 

Table of Contents
Click to Add Image

End-to-End Odoo Services

From implementation and customization to migration, integrations, support, and training we help you maximize the value of Odoo.

Get Started
Search

Book Free Demo

Get real-time responses. Talk with our Industry Experts.

Professional Author

Author
SerpentCS

Created by the SerpentCS Editorial Team, delivering trusted insights on Odoo, ERPNext, Zoho, SAP, custom
software development, and enterprise technology to help businesses grow smarter.

Ready to Take the Next Step?

Whether you're planning a new ERP implementation, migrating from legacy software,
or optimizing your existing system, our experts are here to help.