What Changed in Odoo 19
Odoo 19 is primarily an internal refactoring release. The ORM was reorganized into a package structure, but all existing imports continue to work via re-exports. This makes v18→v19 migration smoother than previous version upgrades.
Change 1: ORM Package Split
The ORM code was reorganized from a single file into odoo/orm/ with submodules:
odoo/orm/fields.py— Field definitionsodoo/orm/models.py— Model base classesodoo/orm/commands.py— O2M/M2M command helpersodoo/orm/domains.py— Domain class
Impact on your code: NONE. All imports via from odoo import fields, models, api continue to work. The split is purely internal.
Change 2: Domain Class
A new AST-based Domain class is available for programmatic domain manipulation. The traditional list-based domain format still works everywhere.
# Traditional (still works)
domain = [('state', '=', 'draft'), ('amount', '>', 1000)]
# New Domain class (optional, for programmatic use)
from odoo.osv.expression import AND, OR
combined = AND([domain1, domain2])Change 3: Constraint and Index Classes
models.Constraint() and models.Index() replace _sql_constraints:
# Odoo 18 (old style)
_sql_constraints = [
('name_unique', 'UNIQUE(name)', 'Name must be unique.'),
]
# Odoo 19 (new style)
_name_unique = models.Constraint(
"UNIQUE(name)",
"Name must be unique."
)
_name_idx = models.Index(
"idx_my_model_name",
"name",
)Migration: Replace _sql_constraints tuples with models.Constraint() class attributes. The old format may still work but is deprecated.
Change 4: web_editor → html_editor + html_builder
The web_editor module was split into:
html_editor— Rich text editing componenthtml_builder— Drag-and-drop page builder
If your module depends on web_editor, update the dependency:
# __manifest__.py
# Odoo 18
'depends': ['web_editor'],
# Odoo 19
'depends': ['html_editor'], # or 'html_builder' if using page builderChange 5: New Decorators
# Mark a method as deprecated
@api.deprecated('Use new_method() instead')
def old_method(self):
return self.new_method()
# Mark a method as private (not callable via RPC)
@api.private
def _internal_helper(self):
passChange 6: rpc Module Extraction
The RPC module was extracted into a separate package. If you import from odoo.http for JSON-RPC endpoints, verify your imports still resolve.
Change 7: api_doc Module
A new api_doc module provides automatic API documentation. No action needed for migration, but useful to know about.
Step-by-Step Migration
- Backup — Full database + filestore backup
- Deploy staging — Create Odoo 19 staging on DeployMonkey
- Update _sql_constraints — Replace with models.Constraint() class
- Update web_editor dependency — Change to html_editor
- Test imports — Verify all imports resolve (they should via re-exports)
- Run tests — Execute your test suite on Odoo 19
- Fix issues — Address any compatibility problems
- Deploy production — After staging validation
AI-Assisted Migration
# Claude Code prompt:
"Migrate my Odoo module from v18 to v19.
Replace _sql_constraints with models.Constraint(),
update web_editor dependency to html_editor,
and check for any deprecated API usage."Claude Code with the Odoo 19 knowledge base handles this migration accurately. Most v18→v19 migrations are straightforward because the breaking changes are minimal.
Getting Started
Deploy Odoo 19 staging on DeployMonkey (free plan). Test your modules. The migration from 18 to 19 is one of the smoothest in recent Odoo history — most modules work without changes.