Bạn đã dựng được trang tùy biến (controller hoặc XML) và đưa nó vào sitemap. Nhưng khách vào website vẫn không tìm thấy nó — vì nó chưa có trên thanh điều hướng. Trang tồn tại không có nghĩa nó xuất hiện trong menu; hai thứ đó tách biệt trong Odoo: website.page là trang, website.menu là mục trên thanh menu. Bài này chỉ cách gắn một trang vào menu — khai bằng XML một mục menu, hiểu cây parent_id/sequence, và một cơ chế thú vị: Odoo tự sao mục menu sang từng website.
website.page và website.menu là hai thứ khác nhau
Điểm dễ nhầm nhất: tạo một website.page không tự tạo mục menu. Trang có URL, truy cập được, vào sitemap được — nhưng thanh menu trên cùng chỉ hiện những gì có trong website.menu. Muốn khách bấm từ menu tới trang, bạn phải tạo cả hai và nối chúng.

Hình 1: Hai bản ghi. website.page (trên) là trang; website.menu (dưới) là mục trên thanh menu, trỏ tới trang qua url. name là chữ hiện trên thanh, parent_id đặt nó dưới menu gốc, sequence quyết định thứ tự. (Có thể dùng page_id thay url để gắn thẳng một website.page.)
Khai xong và -u module, mục "Ưu đãi" hiện ngay trên header website thật:

Hình 2: Thanh menu website thật, giờ có Ưu đãi nằm cạnh Home, Shop, Blog, Jobs, Contact us — bấm vào đi tới /uu-dai-thanh-vien. Không cần chỉnh tay gì thêm; chỉ một bản ghi website.menu.
Cây menu: parent_id, sequence, page_id
website.menu là một cây phân cấp (_parent_store = True), sắp xếp theo sequence. Các trường quan trọng:
name— chữ hiển thị (dịch được).url— đường dẫn khi bấm (nội bộ/...hoặc ngoàihttps://...).parent_id— menu cha; đặt dưới menu gốc để thành mục top, hay dưới một mục khác để thành menu con (dropdown).sequence— thứ tự trái→phải (số nhỏ đứng trước).page_id— gắn thẳng tới mộtwebsite.page(thay vì gõurl); xoá trang thì mục menu tự mất (ondelete='cascade').new_window,group_ids— mở tab mới, hoặc chỉ hiện cho nhóm quyền nhất định.
Nhìn cây menu thật của website qua dữ liệu:

Hình 3: Cây website.menu thật của website. Các mục là con của "Top Menu for Website 1", sắp theo sequence — "Ưu đãi" (seq 65) đứng sau Contact us (seq 60). Đặt sequence nhỏ hơn để đẩy lên trước.
Mỗi website một cây menu — và Odoo tự sao
Đây là cơ chế hay bị bất ngờ. Một cài đặt Odoo có thể chạy nhiều website, mỗi website có cây menu riêng (website.menu_id trỏ tới một "Top Menu" khác nhau). Khi bạn khai một mục menu trong XML dưới "Default Main Menu" (website.main_menu, không thuộc website nào), Odoo tự sao chép nó vào top menu của từng website hiện có.
Đó là lý do sau khi -u, hệ thống có hai bản ghi "Ưu đãi": một bản gốc dưới Default Main Menu, và một bản đã sao dưới "Top Menu for Website 1" — chính bản sao này mới hiện trên header của website 1. Hiểu điều này tránh bối rối khi bạn thấy menu "nhân đôi" trong dữ liệu, hay khi sửa mục ở một website mà website khác không đổi theo.
Quản trị bằng chuột: Menu Editor
Không phải lúc nào cũng cần XML. Người quản trị chỉnh menu ngay trên giao diện: vào Website → Site → Menu Editor (hoặc bấm "Sửa" rồi thao tác trên thanh menu). Ở đó kéo–thả để sắp thứ tự và lồng cấp, thêm/sửa/xoá mục, tạo mega menu. Còn trang thì quản lý ở Website → Site → Pages (bật/tắt công khai, đổi URL, SEO — như phần 170).
Quy tắc chọn: XML khi menu là một phần của module (cài module là có ngay, dựng lại được); Menu Editor khi người vận hành muốn tự chỉnh mà không đụng code.
Vài lưu ý
- Trang và menu tách biệt — tạo trang xong nhớ tạo cả mục menu, nếu muốn khách thấy nó trên thanh.
page_idgắn cứng hơnurl. Dùngpage_idkhi mục menu ứng với mộtwebsite.pagecụ thể — xoá trang, mục menu tự dọn theo. Dùngurlcho link ngoài hay route controller.- Đừng khai trùng cho từng website bằng tay. Khai một lần dưới
website.main_menuvà để Odoo sao đi; can thiệp thủ công vào từng top menu dễ lệch. group_idscho menu theo quyền — ví dụ mục "Khu nội bộ" chỉ hiện với nhân viên đăng nhập.
Ba ý mang về
website.page(trang) vàwebsite.menu(mục menu) là hai thứ khác nhau — tạo trang không tự tạo menu; phải khaiwebsite.menu(name+url/page_id+parent_id+sequence) để nó hiện trên thanh điều hướng.- Menu là cây sắp theo
sequence, lồng cấp bằngparent_id(menu con/dropdown);page_idgắn cứng một trang (cascade khi xoá trang). - Mỗi website một cây menu, và Odoo tự sao mục khai dưới
website.main_menusang top menu từng website — nên bạn thấy bản gốc + bản sao; quản trị còn kéo–thả được trong Menu Editor.
Ta đã đi hết một vòng website và controller. Phần sau quay lại một chủ đề bảo mật đã chạm tới nhưng chưa mổ kỹ: Phần sau đào sâu CSRF trong controller và form — token hoạt động ra sao, khi nào bật/tắt, và những cạm bẫy khi để sai làm form gãy hoặc mở lỗ hổng.