Ta đã đi qua các loại action phức tạp: window action (mở view), server action (chạy code), client action (vẽ màn hình JS). Bây giờ tới loại đơn giản nhất — và vì thế dễ quên: URL action (ir.actions.act_url). Nó không mở view, không chạy JS, không cần gì cả; chỉ điều hướng trình duyệt tới một url. Mở trang ngoài, tải một file PDF, nhảy tới một tài liệu — tất cả gói trong một dict ba khoá. Bài này gắn một URL action thật vào form thẻ.

Một dict ba khoá

URL action chỉ cần ba thứ: type là ir.actions.act_url, url là địa chỉ, target chọn mở ở đâu. Tôi thêm một method trả về đúng dict đó:

Ảnh chụp đoạn mã nền tối gồm method Python action_mo_website trả về dict với type ir.actions.act_url, url ghép từ coffeecode.vn posts và tên thẻ, target new kèm chú thích new là tab mới self là cùng tab; phần nút button name action_mo_website type object string Mở website quán icon external link; phần khai tĩnh bằng record model ir.actions.act_url với field url tới odoo documentation và target new; kèm chú thích dùng khi mở trang ngoài tải file báo cáo link tài liệu, url tương đối hoặc tuyệt đối, không cần view không cần JS

Hình 1: URL action ba cách nhìn. Method Python trả dict act_url (ở đây ghép url theo mã thẻ). Nút type="object" gọi method. Hoặc khai tĩnh bằng <record model="ir.actions.act_url"> khi url cố định. target: new (tab mới) hay self (cùng tab).

Method trả về gì — kiểm bằng shell

Bản chất URL action nằm ở dict nó trả về. Gọi thẳng method trong odoo shell:

Ảnh chụp phiên odoo shell gọi method action_mo_website trên thẻ id 1, kết quả trả về một dict với type ir.actions.act_url, url là https coffeecode.vn posts VIP-0001, target new; kèm chú thích web client nhận dict này rồi điều hướng trình duyệt tới url, không cần view không cần JS chỉ một dict ba khoá

Hình 2: Method trả về {'type': 'ir.actions.act_url', 'url': 'https://coffeecode.vn/posts/VIP-0001', 'target': 'new'}. Web client nhận dict này và điều hướng trình duyệt tới url — mở tab mới vì target='new'. Toàn bộ "action" chỉ là ba khoá.

Nút trên form

Nút gọi method hiện ngay ở header form, kèm biểu tượng liên kết ngoài:

Ảnh chụp giao diện Odoo thật header form thẻ VIP-0002 với dải nút Gia hạn thẻ, Cộng điểm, và nút Mở website quán kèm biểu tượng mũi tên ra ngoài; bên phải là thanh trạng thái Mới cấp Đang dùng Hết hạn; bên dưới là tiêu đề Mã thẻ VIP-0002 màu nâu

Hình 3: Nút "Mở website quán" (biểu tượng liên kết ngoài) nằm cạnh các nút hành động khác. Bấm nó, method chạy, trả act_url, và trình duyệt mở coffeecode.vn/posts/VIP-0002 trong tab mới. Không rời Odoo, chỉ bật thêm một tab.

Dùng URL action khi nào

  • Mở trang ngoài: website công ty, trang tra cứu, một dịch vụ bên thứ ba với tham số lấy từ bản ghi.
  • Tải file / báo cáo: url trỏ tới /report/pdf/<report>/<id> để tải PDF, hay một đường dẫn file trong Odoo. (Report action là chủ đề bài sau.)
  • Link tài liệu, hướng dẫn: nút "Trợ giúp" mở tài liệu ngoài.
  • url tương đối hay tuyệt đối đều được: tương đối (/web/...) ở trong Odoo, tuyệt đối (https://...) ra ngoài.

Lưu ý nhỏ: target='new' mở tab mới — hợp khi muốn giữ người dùng ở lại Odoo; target='self' thay cả trang hiện tại (dùng khi thật sự muốn "đi khỏi").

Ba ý mang về

  1. URL action (ir.actions.act_url) chỉ điều hướng trình duyệt tới một url — action đơn giản nhất, không view/JS; gồm ba khoá type, url, target.
  2. target: new (tab mới, giữ Odoo) hoặc self (cùng tab, rời đi); khai bằng record XML (url cố định) hoặc method Python trả dict (url động theo bản ghi).
  3. Hợp cho: mở trang ngoài, tải file/báo cáo (/report/pdf/...), link tài liệu; url tương đối hay tuyệt đối đều dùng được.

Nhắc tới tải PDF, đó chính là mảnh ghép cuối của chuỗi action — và là bài tròn 100: Phần sau về report action và QWeb PDF — cách Odoo dựng một báo cáo in được từ template QWeb, xuất ra PDF cho hoá đơn, phiếu, thẻ.