How to Build Custom Odoo Modules: A Developer's Guide to OWL, ORM & Inheritance

Developer guide to building custom Odoo modules. Covers module structure, OWL framework, ORM inheritance, views, security rules, testing, and OCA guidelines.

E

ECOSIRE Research and Development Team

ECOSIRE Team

March 5, 20264 min read748 Words

How to Build Custom Odoo Modules: A Developer's Guide to OWL, ORM & Inheritance

When Odoo's 82 official modules and 40,000+ community modules do not cover your exact requirements, custom development fills the gap. This guide covers module structure, ORM patterns, inheritance mechanisms, and best practices for 2026.

Key Takeaways

  • Every custom module follows a standard directory structure — models, views, security, static, tests — with a __manifest__.py defining metadata and dependencies.
  • Three inheritance types enable extending Odoo without forking: class inheritance (add fields/methods to existing models), prototype inheritance (create new models based on existing ones), and delegation inheritance (link models via composition).
  • OWL 3 is Odoo 18's frontend framework — reactive components with setup(), hooks, and XML templates replace the legacy widget system.
  • Security requires both ACL (ir.model.access.csv) and record rules — ACL controls model-level CRUD permissions, record rules filter which records users can access.
  • Follow OCA guidelines — use pre-commit hooks, write TransactionCase tests, and avoid sql.raw() for maintainability and upgrade safety.

Module Directory Structure

my_custom_module/
├── __init__.py
├── __manifest__.py
├── models/
│   └── my_model.py
├── views/
│   ├── my_model_views.xml
│   └── menu.xml
├── security/
│   ├── ir.model.access.csv
│   └── security.xml
├── static/src/
│   ├── js/
│   └── xml/
└── tests/
    └── test_my_model.py

The __manifest__.py defines name, version, category, dependencies, data files, and installable flag.

ORM Fundamentals

Odoo models inherit from models.Model (persistent) or models.TransientModel (temporary wizards). Define fields with fields.Char, fields.Integer, fields.Many2one, fields.One2many, etc. Computed fields use @api.depends decorator. Constraints use @api.constrains or SQL constraints.

Key ORM methods: create(), write(), unlink(), search(), read(). Override these to add custom logic while calling super() to preserve base behavior.

Three Inheritance Types

Class inheritance (_inherit): Add fields and methods to an existing model. The most common pattern.

Prototype inheritance (_inherit + _name): Create a new model that copies structure from an existing one. Each model has its own database table.

Delegation inheritance (_inherits): New model links to an existing model via a Many2one field. Records in both tables are created automatically.

OWL 3 Frontend Components

OWL 3 uses reactive state management with useState, lifecycle hooks via setup(), and XML templates. Components register via registry.category("actions") or patch existing components.

const { Component, useState } = owl;
class MyComponent extends Component {
  setup() {
    this.state = useState({ count: 0 });
  }
}
MyComponent.template = "my_module.MyComponent";

Security Model

Access Control Lists (ACL): ir.model.access.csv defines CRUD permissions per model per group.

Record Rules: XML rules filter which records users can access using domain expressions. Example: users see only records from their own company.

Always define both ACL and record rules. ACL without record rules gives full table access. Record rules without ACL still blocks the model entirely.

Testing

Write tests using TransactionCase (each test in a transaction that rolls back) or HttpCase (for testing web controllers). Run with odoo-bin --test-enable -d testdb -i my_module.

Test CRUD operations, computed fields, constraints, access rules, and workflow transitions.

OCA Best Practices

Follow OCA coding standards: use pre-commit hooks for linting, document public methods, avoid direct SQL (use the ORM), keep models under 500 lines, use meaningful variable names, and write tests for all business logic.

Never use sql.raw() — always use parameterized queries or ORM methods to prevent SQL injection.

Frequently Asked Questions

Q: How long does it take to build a custom Odoo module? A: Simple modules (new model, views, basic logic) take 1-3 days. Medium complexity (workflow automation, integrations, reports) takes 1-4 weeks. Complex modules (multi-model systems, OWL components, API integrations) take 1-3 months.

Q: Should I use Odoo Studio or custom development? A: Studio is excellent for adding fields, simple automations, and report modifications without code. Use custom development for complex business logic, performance-critical features, API integrations, or anything that needs version control and testing.

Q: How do I ensure my module survives Odoo version upgrades? A: Follow OCA guidelines, use the inheritance system instead of overriding core code, avoid deprecated APIs, write comprehensive tests, and document all customizations. Modules following these practices typically require 2-8 hours of migration work per version.

Q: Can I sell custom modules on the Odoo App Store? A: Yes. Package your module following Odoo's marketplace guidelines, include documentation, set pricing, and submit for review. Modules must pass automated quality checks and manual review before publication.

Next Steps

Need custom Odoo development? ECOSIRE's customization services build tailored modules following OCA standards. Contact us to discuss your requirements.

E

Written by

ECOSIRE Research and Development Team

Building enterprise-grade digital products at ECOSIRE. Sharing insights on Odoo integrations, e-commerce automation, and AI-powered business solutions.

Chat on WhatsApp