Many2one trỏ tới một model cố định — partner_id luôn là res.partner. Nhưng đôi khi bạn cần một trường linh hoạt hơn: "nguồn gốc" của bản ghi có thể là khách hàng, đơn hàng, hay người dùng — tùy trường hợp. Đó là việc của Reference và họ hàng Many2oneReference. Khép lại chương "trường quan hệ", bài này bàn hai kiểu trường ít gặp nhưng mạnh.

Reference: Many2one động

Reference cho phép một trường trỏ tới bản ghi của bất kỳ model nào trong một danh sách định sẵn:

Trường Reference trỏ tới bản ghi của model bất kỳ trong Odoo 19: Many2one trỏ một model cố định còn Reference trỏ nhiều model; Many2one luôn là res.partner, partner_id bằng fields.Many2one res.partner; Reference chọn một trong danh sách model rồi chọn bản ghi, nguon_goc bằng fields.Reference với selection là list cặp res.partner Khách hàng, sale.order Đơn hàng, res.users Người dùng; gán bằng chuỗi model phẩy id, rec.nguon_goc bằng res.partner phẩy 15 hoặc phần trăm s phẩy phần trăm s theo model và id, đọc rec.nguon_goc ra recordset thật res.partner 15; Reference vs Many2oneReference, Reference lưu chuỗi model phẩy id trong một cột tiện nhưng không index không khóa ngoại, Many2oneReference là id int cộng trường model_name riêng nhanh hơn dùng cho quan hệ động hiệu năng cao ví dụ mail.message res_id cộng model

Hình 1: Reference(selection=[...]) khai danh sách model được phép trỏ. Gán bằng chuỗi 'model,id' (ví dụ 'res.partner,15'). Đọc ra là recordset thật. Khác Many2oneReference ở dưới: Reference gói tất cả vào một cột chuỗi; Many2oneReference tách id (int) và tên model thành hai trường — nhanh hơn.

Cho nó chạy thật — 1 field, 3 model

Tôi thêm field nguon_goc kiểu Reference vào module, rồi gán nó tới ba model khác nhau. Output thật trên db blog19:

Reference chạy thật một field trỏ ba model trên database blog19: cùng field nguon_goc gán tới ba model khác nhau, t1.nguon_goc bằng res.partner phẩy 15 cho recordset res.partner 15 tên Cà Phê Việt Chi nhánh Hà Nội, t2.nguon_goc bằng sale.order phẩy 15 cho sale.order 15 tên S00015, t3.nguon_goc bằng res.users phẩy 1 cho res.users 1 tên OdooBot; đọc ra là recordset thật gọi field method như bình thường; cơ sở dữ liệu lưu chuỗi model phẩy id trong một cột, SELECT name nguon_goc từ bảng quan_the_thanh_vien cho REF-1 res.partner phẩy 15, REF-2 sale.order phẩy 15, REF-3 res.users phẩy 1; một cột giữ được tham chiếu tới bất kỳ model nào trong danh sách

Hình 2: Output thật. Cùng field nguon_goc trỏ tới res.partner(15) ("Cà Phê Việt..."), sale.order(15) ("S00015"), và res.users(1) ("OdooBot"). Đọc ra là recordset thật — gọi field/method bình thường. Nhìn SQL thô: CSDL lưu đúng chuỗi 'res.partner,15', 'sale.order,15', 'res.users,1' trong một cột duy nhất.

Cái giá của sự linh hoạt

Reference tiện nhưng có nhược điểm, do nó lưu chuỗi 'model,id' trong một cột:

  • Không có khóa ngoại (FK): CSDL không đảm bảo bản ghi được trỏ tồn tại — xóa bản ghi đích thì Reference thành "trỏ trống".
  • Không index tốt: lọc/join theo Reference chậm hơn Many2one.
  • Domain phức tạp hơn: không lọc xuyên quan hệ dễ như Many2one.

Vì vậy: chỉ dùng Reference khi thật sự cần trỏ nhiều model. Nếu chỉ một model, luôn dùng Many2one (nhanh, có FK, index).

Many2oneReference: bản hiệu năng cao

Khi cần quan hệ động nhiều dữ liệu, cần nhanh, Odoo dùng Many2oneReference — tách thành hai trường:

res_model = fields.Char('Model')                          # tên model, ví dụ 'res.partner'
res_id = fields.Many2oneReference('ID', model_field='res_model')  # id (int)

res_id là số nguyên (index được, nhanh), res_model giữ tên model riêng. Đây chính là cách mail.message, mail.activity gắn "ghi chú/hoạt động" vào bất kỳ bản ghi nào trong toàn hệ thống — hàng triệu dòng vẫn nhanh.

  • Reference: gọn, một cột, hợp trường ít dùng, ít dữ liệu.
  • Many2oneReference: hai trường, id là int, hợp quan hệ động khối lượng lớn.

Khi nào dùng cái nào

Nhu cầu Dùng
Trỏ một model cố định Many2one (mặc định, tốt nhất)
Trỏ nhiều model, ít dữ liệu Reference
Trỏ nhiều model, khối lượng lớn/cần nhanh Many2oneReference

Nhớ ba ý

  1. Reference là "Many2one động": trỏ tới bản ghi của bất kỳ model nào trong selection, lưu chuỗi 'model,id' một cột — đo thật: 1 field trỏ được res.partner/sale.order/res.users.
  2. Cái giá: không FK, không index tốt — chỉ dùng khi thật sự cần nhiều model; một model thì luôn Many2one.
  3. Quan hệ động khối lượng lớn dùng Many2oneReference (id int + trường model riêng) — cách mail.message gắn vào mọi bản ghi mà vẫn nhanh.

Vẫn còn một kiểu trường rất mới và linh hoạt của Odoo. Phần sau đi vào trường Properties — cho phép mỗi bản ghi có schema riêng, tùy biến động mà không cần thêm cột, một tính năng mạnh của Odoo hiện đại.