Khichdi InfoTech
Skip to content

Odoo Development · intro · 10 min read

Understanding Odoo Module Structure

How Odoo addons are laid out: manifests, models, views, security, data, and dependency order — the foundation every developer ticket should respect.

Last reviewed 2026-07-30 · Estimated effort: 1–2 weeks typical discovery

Table of contents

An Odoo module is a Python package with a manifest that declares name, version, dependencies, and installable data files. The server loads models from models/, views from views/, and enforces security from security/ — in dependency order.

Predictable structure reduces merge conflicts, speeds code review, and makes -u upgrades traceable. Scattering logic across unrelated folders or skipping manifest entries is a common source of works-on-my-machine failures.

Treat __manifest__.py as the contract: if a file is not listed, it will not install on a fresh database. Cross-module inheritance belongs in separate addons with explicit depends, not hidden monkey-patches.

Before writing fields or xpath expressions, know where they live. Odoo's module loader is opinionated — fighting its layout creates fragile addons that break on the next install.

This article maps the standard directory tree, manifest keys that matter in Odoo 16/17, and how files are processed during module install and upgrade.

__manifest__.py defines technical name, human title, version, depends, application flag, and the ordered data list. Odoo processes data files top to bottom; security CSV before views that reference new models, demo data last.

Use semantic versioning aligned with your Odoo target (e.g. 17.0.1.0.0). Bump the version on every -u-worthy change so operators know staging must run an upgrade.

  • depends: only what you import or inherit at load time
  • data vs demo: keep demo out of production installs
  • assets: register JS/SCSS under web.assets_backend when needed
  • post_init_hook / uninstall_hook: sparingly, document side effects

models/__init__.py imports each model file; each file typically defines one Model class. Wizards go in wizard/, controllers in controllers/, report Python in report/. Keep __init__.py at module root importing subpackages.

Use _inherit for extending existing models and _name only when defining new business tables. Split large domains into multiple files (sale_custom.py, sale_custom_line.py) rather than thousand-line monoliths.

views/ holds form, list, kanban, search, and inherited view XML. security/ holds ir.model.access.csv and record-rule XML. data/ holds cron, mail templates, sequences, and noupdate=1 master data when appropriate.

static/description/icon.png and index.html power the Apps list. i18n/*.po files sit at module root for translations.

If module B inherits views or models from module A, B must list A in depends. Circular depends are rejected; implicit ordering via auto_install is for Odoo core patterns, not ad-hoc shortcuts.

For multi-company or bridge modules (sale_stock_custom), create thin glue modules rather than stuffing cross-app logic into one mega-addon.

Prefix custom modules with your company or project code (kitech_sale_approval) to avoid collisions with App Store modules. One Git repo can hold many addons; document addons_path for each environment.

Never edit files under odoo/addons or enterprise paths — only your addons_path. Forked core changes are upgrade blockers.

  • Maintain a module template with manifest, security stub, and empty model scaffold.
  • List every XML/CSV in data; verify fresh -i on a clean DB before merging.
  • Split modules by bounded context — sales approval vs manufacturing routing should not share one manifest.
  • Document depends rationale in README or module description for future reviewers.
  • Keep hooks idempotent; post_init_hook should tolerate re-run after failed upgrade.
  • Align folder names with Odoo conventions so IDE search and Odoo.sh builds stay predictable.

  • !Adding XML files without updating __manifest__.py data list.
  • !Depending on sale_management when only sale is required — pulls unnecessary UI.
  • !Putting business logic in XML automated actions instead of Python models.
  • !Using duplicate technical module names across projects copied from GitHub.
  • !Mixing translation strings and hard-coded labels without _() in Python.
  • !Creating circular depends by importing models at module level across addons.

Module structure is not bureaucracy — it is how Odoo finds, secures, and upgrades your code. A clean manifest and folder layout pays back on every -u.

Next, learn how the ORM loads these models and executes create/write/unlink in transactions.

Tree: __manifest__.py, models/, views/, security/, data/, static/.
  • __manifest__.py

  • models/

  • views/

  • security/

  • data/

  • manifestmodels
  • modelsviews
  • modelssec
Install flow: parse manifest → load Python → load data files in order.
1

Trigger

Business event starts the flow.

2

Execute

Operate in the system of record.

3

Validate

Check outcomes and exceptions.

4

Close

Reconcile and hand off.

Pre-merge: manifest data list, depends, fresh -i, icon, ACL stub.
  • Owners named
  • UAT scripts signed
  • Rollback documented
  • Hypercare roster ready

Frequently asked questions

Can one Python file define multiple models?

Yes, but one model per file is the community convention and simplifies reviews. Group tightly coupled abstract mixins in the same file only when they are never used alone.

What is the difference between data and demo in the manifest?

data loads on every install/upgrade unless noupdate prevents writes. demo loads only when demo mode is enabled — keep sample records out of data for production paths.

How do I add a module to an existing database?

Place it on addons_path, update apps list, install via UI or -i module_name. Dependent modules may need -u if your new module extends their views.

Should reports live in the same module as the model?

Usually yes for cohesion. Split only when report packages are optional or licensed separately — still declare depends explicitly.

Need help untangling a messy addons tree?

We refactor multi-module estates into clear boundaries with documented depends and upgrade paths.

Business technology and software delivery