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:

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:

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 ý
- 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. - 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.
- Quan hệ động khối lượng lớn dùng Many2oneReference (id int + trường model riêng) — cách
mail.messagegắ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.