Suốt loạt bài, ta dùng Odoo. Ba bài cuối mở nắp capo cho ai muốn viết thêm tính năng. Và tin vui: kiến trúc Odoo gọn gàng đến bất ngờ — mỗi "app" bạn thấy trong màn hình Ứng dụng thật ra chỉ là một thư mục trên đĩa, tuân theo vài quy ước. Hiểu cấu trúc đó là bước một của lập trình Odoo.

Bài này ở mức nâng cao (cần biết chút Python). Nhưng mình sẽ giải thích để cả người chưa code Odoo bao giờ vẫn hình dung được.

Một module = một thư mục theo quy ước

Ta dựng thử một module mẫu tên quan_ca_phe (quản lý thẻ thành viên cho quán). Đây là cây thư mục thật của nó:

Cây thư mục module Odoo quan_ca_phe: gốc quan_ca_phe chứa init.py, manifest.py, và các thư mục models (the_thanh_vien.py), views (the_thanh_vien_views.xml), security (ir.model.access.csv), data (hang_the_data.xml), static (src/css/the.css), mỗi mục kèm chú thích vai trò

Hình 1: Cây thư mục module quan_ca_phe. Odoo nhận ra đây là module nhờ hai file bắt buộc ở gốc: __manifest__.py (giấy khai sinh) và __init__.py (nạp code Python). Các thư mục con là quy ước — Odoo và lập trình viên khác nhìn tên là biết vai trò.

Vai trò từng phần:

  • __manifest__.py — khai báo module (tên, phiên bản, phụ thuộc, file cần nạp). Thiếu file này, Odoo không thấy thư mục là một module.
  • __init__.py — file Python báo "hãy nạp các thư mục con" (ở đây nạp models/).
  • models/ — định nghĩa bảng dữ liệu bằng Python (mỗi model ≈ một bảng trong CSDL).
  • views/ — giao diện (form, list, menu) viết bằng XML.
  • security/ — phân quyền: ai được đọc/ghi bảng nào (file CSV).
  • data/ — dữ liệu nạp sẵn khi cài (danh mục mặc định...).
  • static/ — tài nguyên web: CSS, JS, ảnh.

Tên thư mục module (quan_ca_phe) chính là tên kỹ thuật — chỉ chữ thường, số, gạch dưới; không dấu, không cách.

Trái tim: file manifest.py

Đây là file Odoo đọc đầu tiên. Nó là một từ điển Python khai báo mọi thứ về module:

Nội dung file manifest.py thật của module quan_ca_phe: từ điển Python với các khoá name, version 19.0.1.0.0, summary, description, author, website, category Sales, license LGPL-3, depends base và contacts, data liệt kê 3 file, assets web.assets_backend, installable True, application True

Hình 2: File __manifest__.py thật (đúng cú pháp Odoo 19). Các khoá quan trọng: name (tên hiển thị), version (19.0.1.0.0 — hai số đầu là phiên bản Odoo), depends (module này cần base và contacts cài trước), data (danh sách file XML/CSV Odoo sẽ nạp, đúng thứ tự), license, application: True (hiện thành một "app" ở màn hình Ứng dụng).

Vài khoá đáng nhớ:

  • depends: khai đúng phụ thuộc. Model của bạn dùng res.partner? Phải depends module có nó (base/contacts), nếu không Odoo báo lỗi khi cài.
  • data: liệt kê file cần nạp — thứ tự quan trọng: security trước, rồi views, rồi data. Sai thứ tự có thể lỗi "không tìm thấy model/quyền".
  • installable: True: cho phép cài. application: True: hiện như một app độc lập.

Sai một dấu phẩy trong file này là cả module không nạp được — nên nó cũng là chỗ đầu tiên cần soi khi lỗi.

Odoo lắp ghép mọi thứ thế nào?

Khi bạn bấm cài module, Odoo:

  1. Đọc __manifest__.py → biết phụ thuộc, cài chúng trước.
  2. Chạy __init__.py → nạp code trong models/ → tạo/ cập nhật bảng trong PostgreSQL theo các model.
  3. Nạp lần lượt các file trong data → dựng quyền, giao diện, dữ liệu mẫu.
  4. Gắn tài nguyên trong static vào web.

Toàn bộ chỉ từ một thư mục đặt đúng chỗ (thư mục addons). Đặt module vào, cài, là có thêm tính năng — gỡ ra thì sạch. Kiến trúc "cắm-là-chạy" này là lý do Odoo dễ mở rộng.

Mẹo cho người mới lập trình Odoo

  • Đừng viết tay từ số 0 — Odoo có lệnh scaffold dựng sẵn khung thư mục chuẩn để bạn điền vào.
  • Tên kỹ thuật đặt có tiền tố (ví dụ quan_ ) để không đụng module khác.
  • Bật Chế độ nhà phát triển để xem tên model, tên field, file — cực kỳ cần khi code.
  • Đọc module có sẵn (như mrp, sale) để học cách người ta tổ chức — code Community mở, đọc thoải mái.

Nhớ ba ý

  1. Một module Odoo = một thư mục có __manifest__.py (giấy khai sinh) + __init__.py, cùng các thư mục quy ước models/ views/ security/ data/ static/.
  2. __manifest__.py khai name, version, depends (phụ thuộc), data (file nạp — đúng thứ tự) — sai cú pháp là cả module hỏng.
  3. Cài module = Odoo đọc manifest → nạp models (tạo bảng) → nạp quyền/giao diện/dữ liệu — kiến trúc "cắm-là-chạy" dễ mở rộng.

Có khung module rồi, giờ viết phần lõi: một model. Phần sau ta viết model Python đầu tiên — vài dòng code biến thành một bảng dữ liệu có giao diện trong Odoo.