How to Implement Field-Level Constraints in Odoo?


✅ What Are They?

Both are used to validate data and enforce business rules in Odoo, but they differ in where and how they work.


Feature

@api.constrains

SQL Constraints (_sql_constraints)

Type

Python-based ORM constraint

PostgreSQL-level constraint

Triggered On

create() and write()

Automatically at the DB level

Can Be Conditional

✅ Yes

❌ No (purely structural)

Supports Complex Logic

✅ Yes (if/else, cross-field validation)

❌ No

User Feedback

ValidationError in Python

DB-level error message



📌 Realistic Use Case 1: Prevent Duplicate Emails on Customers


Using SQL Constraint

_sql_constraints = [

    ('email_unique', 'unique(email)', 'Email must be unique.')

]

  • Applied at the database level.
  • Prevents duplicate values.
  • Fast and efficient, but only for simple, single-field rules.



📌 Realistic Use Case 2: Ensure Discount ≤ 50% for Special Products

Using @api.constrains

from odoo.exceptions import ValidationError

@api.constrains('discount', 'product_id')

def _check_discount_limit(self):

    for line in self:

        if line.product_id.is_special and line.discount > 50:

            raise ValidationError("Discount cannot exceed 50% for special products.")


  • Triggers when discount or product_id is changed.
  • Can use custom logic, conditions, and multiple fields.
  • Ideal for business logic validations.


⚙️ When to Use What?


Scenario

Use @api.constrains

Use SQL Constraint

Cross-field validation

✅ Yes

❌ No

Simple uniqueness or non-null checks

❌ No

✅ Yes

Dynamic rules based on other fields

✅ Yes

❌ No

Performance-critical constraints

❌ Slower

✅ Faster

Needs translatable error messages

✅ Yes

✅ Yes



✅ Summary Table


Criteria

@api.constrains

SQL Constraint (_sql_constraints)

Level

Application / ORM

Database

Complex conditions

✅ Supported

❌ Not supported

Cross-field validation

✅ Yes

❌ No

Automatic enforcement

On create/write in ORM

On DB commit

Error type

ValidationError

DB constraint violation error

Customizable message

✅ Yes

✅ Yes


✅ Best Practices

  • Use SQL constraints for structural validation (e.g., uniqueness).
  • Use @api.constrains for business logic validation involving conditions or multiple fields.
  • Avoid putting complex logic inside SQL constraints;