Đổi một website Odoo sang "giao diện quán cà phê" hay "giao diện spa" — cài một theme là cả site đổi màu, đổi font, đổi bố cục header/footer, nhất quán từ trang chủ tới trang sản phẩm. Điều thú vị: theme không phải một mớ file CSS ghi đè lộn xộn. Nó là một module khai màu/font qua một hệ biến SCSS có kỷ luật, để đổi một chỗ là cả site đổi theo. Bài này mổ xẻ cấu trúc cơ bản của một theme Odoo 19 — manifest, hệ biến màu, cơ chế "color combination" — và cho thấy nó áp lên toàn site ra sao.

Theme là một module đặc biệt

Điểm bất ngờ với người mới: theme cũng là một module như mọi module khác, chỉ khác vài chi tiết trong __manifest__. Đây là manifest thật của theme_default (theme mặc định của Odoo):

Ảnh chụp mã Python nền tối manifest của theme, một module đặc biệt. Dict gồm name Default Theme, category Theme chú thích hiện ở kho Theme không phải app, depends website chú thích theme luôn phụ thuộc website, data khai data generate_primary_template xml, images khai static description cover png và theme_default screenshot jpg chú thích ảnh cho trình chọn theme, license LGPL-3. Chú thích cài theme là cài module này gỡ hoặc đổi theme đổi toàn bộ giao diện site, cấu trúc thư mục theme gồm static src scss màu font, views template header footer snippet, static description ảnh preview. Phần dưới khai màu font kế thừa biến SCSS primary: file static src scss primary_variables scss của theme, o-color-palettes map-merge với my-theme o-color-1 màu chính nút nhấn 714B67 o-color-2 trắng, o-theme-font-configs preset font chữ

Hình 1: Manifest theme khác module thường ở ba điểm: 'category': 'Theme' (để nó hiện trong kho Theme, không lẫn với app), depends: ['website'], và 'images' — ảnh cover/screenshot hiện trong trình chọn theme. Nội dung theme nằm ở static/src/scss (màu/font), views/ (template header/footer, snippet), static/description (ảnh preview). Cài theme = cài module này.

Khai màu bằng hệ biến SCSS, không phải CSS thô

Đây là chỗ khác biệt lớn nhất với "tự viết CSS". Theme không ghi .btn { background: purple } khắp nơi. Nó khai vài biến SCSS trong một file primary_variables.scss, và toàn bộ giao diện tự lấy từ đó. Nhìn lõi thật của Odoo 19:

Ảnh chụp mã SCSS nền tối file website static src scss primary_variables scss lõi thật. Odoo 19 dùng bảng màu palette cộng color combination o-cc1 tới o-cc5. Mỗi bảng màu định nghĩa o-color-1 tới 5: biến o-color-palettes là map gồm base-1 với o-color-1 màu 984c46, base-2 với o-color-1 màu B99932, và tiếp. Gán vai trò cho từng vùng qua o-cc color combination: biến o-base-color-palette gồm menu bằng 1 header dùng o_cc1, footer bằng 2 footer dùng o_cc2. Chú thích o_cc1 là nền chữ nút của tổ hợp 1 button-primary bằng o-color-1. Ghi chú nút Contact Us Add to cart lấy o-color-1 mặc định 714B67, đổi palette là đổi o-color-1 tới 5 cả site đổi màu nhất quán

Hình 2: Hệ màu thật. $o-color-palettes là các bảng màu, mỗi bảng có o-color-1..5. $o-base-color-palette gán vai trò: menu: 1 (header dùng "color combination" o_cc1), footer: 2 (dùng o_cc2)... Nút primary lấy o-color-1. Đổi một palette là đổi o-color-1..5, và cả site đổi màu nhất quán vì mọi thứ tham chiếu về đó.

Color combination (o_cc1..o_cc5) là ý tưởng cốt lõi của Odoo 19: thay vì đặt màu cho từng phần tử, bạn định nghĩa 5 "tổ hợp màu" (mỗi tổ hợp gồm nền + chữ + tiêu đề + nút + link ăn khớp nhau), rồi gán mỗi vùng (header, footer, section) dùng tổ hợp nào. Nhờ đó đổi màu không bao giờ ra một trang "chỗ tím chỗ cam đá nhau".

Theme áp lên toàn site

Kết quả: cài theme (hoặc đổi palette), cả site khoác màu mới. Đây là site đang chạy với theme mặc định — màu chính #714B67:

Ảnh chụp trang shop thật trên Odoo 19 với theme mặc định. Header Your Logo, menu Home Shop Blog Jobs Contact us, nút Contact Us màu tím. Tiêu đề All products, các chip lọc Cà phê đóng gói Phụ kiện, ô Search, bộ lọc bên trái Khối lượng 250g 500g 1kg, Kiểu rang Rang vừa Rang đậm, Price Range với thanh trượt màu tím từ 95000 đến 260000. Ba sản phẩm Cà phê rang xay Arabica 185000, Cà phê phin truyền thống 1kg 260000, Cà phê hòa tan hộp 20 gói 95000

Hình 3: Site thật với theme mặc định. Nút "Contact Us", thanh trượt giá, các nhấn nhá — tất cả dùng màu chính #714B67 (đo được từ nút: rgb(113,75,103)), font và bố cục cũng từ theme. Không có CSS rải rác; đổi o-color-1 trong palette là những chỗ này đổi theo.

Vài điều nên biết

  • Chỉ một theme hoạt động mỗi lúc. Đổi theme là gỡ theme cũ, cài theme mới; dữ liệu (trang, sản phẩm) giữ nguyên, chỉ lớp giao diện đổi.
  • Đừng ghi màu cứng. Trong snippet/template của bạn, dùng class color-combination (o_cc1..o_cc5) hoặc biến SCSS, đừng gõ #714B67 — để theme kiểm soát, đổi palette là bạn ăn theo.
  • generate_primary_template.xml trong theme_default gọi một hàm sinh các template snippet mặc định — theme không chỉ có màu mà còn khai bố cục/preset.
  • Người quản trị đổi màu không cần code: Website có bảng chọn palette và tùy chỉnh màu/font ngay trên trình soạn — đó chính là ghi đè các biến SCSS này.

Ba ý mang về

  1. Theme là một module đặc biệt: manifest có category: 'Theme', depends: ['website'], images cho trình chọn; nội dung ở static/src/scss (màu/font), views/ (template), static/description (preview). Cài theme = cài module, đổi toàn site.
  2. Màu/font khai bằng hệ biến SCSS: $o-color-palettes (mỗi bảng có o-color-1..5), và color combination o_cc1..o_cc5 gán tổ hợp màu cho từng vùng (menu, footer...) — đổi palette là cả site đổi nhất quán.
  3. Đừng ghi màu cứng — dùng o_cc*/biến SCSS trong snippet để ăn theo theme; người quản trị đổi palette/font ngay trên trình soạn website mà không cần sửa code.

Hết mảng website/theme, phần sau quay lại tầng thấp của controller: Phần sau mổ xẻ redirect và xử lý Werkzeug trong route — cách trả chuyển hướng đúng cách, làm việc với đối tượng request/response thô của Werkzeug, và những cạm bẫy khi tự dựng Response.