Mọi truy vấn Odoo — search, search_count, search_read, record rules, action, view — đều nhận một domain làm điều kiện lọc. Nó là "câu WHERE" của Odoo, viết bằng Python. Hiểu domain thành thạo là chìa khoá để lọc dữ liệu chính xác. Tiếp nối ba phương thức truy vấn, bài này mổ xẻ cú pháp domain cơ bản.
Cấu trúc: danh sách các bộ ba
Domain là một list, mỗi phần tử là một bộ ba (field, toán_tử, value):

Hình 1: Một điều kiện = (field, toán_tử, value). Nhiều bộ ba trong list được nối bằng VÀ (AND) ngầm định. Bảng toán tử hay dùng: so sánh (=, !=, >, <), tập hợp (in, not in), chuỗi (like, ilike), và mẫu đặc biệt =False cho trường trống. Dấu chấm cho phép xuyên quan hệ.
Chạy thật để thấy ý nghĩa
Cách nhanh nhất để hiểu domain là đếm thật. Đây là output từ odoo shell trên res.partner (30 bản ghi) của db blog19:

Hình 2: Domain thật. [] (rỗng) = tất cả (30). ('is_company','=',True) = 6; != cho phần bù (24). ('id','>',20) so sánh số. ('email','=',False) bắt trường trống. Đáng chú ý: ilike 'minh' trả 3 (khớp "Hồ Chí Minh"), còn like 'minh' trả 0 vì like phân biệt hoa thường. Nhiều bộ ba nối AND ngầm. Và country_id.code — xuyên quan hệ bằng dấu chấm.
Bốn điểm phải nắm
1. like vs ilike — hoa thường
like phân biệt hoa thường, ilike không. Thực tế gần như luôn dùng ilike để tìm theo chuỗi — người dùng gõ "minh" vẫn ra "Hồ Chí Minh". Số đo ở Hình 2 chứng minh rõ: cùng chuỗi 'minh', ilike ra 3, like ra 0.
2. Trường trống dùng = False
Odoo biểu diễn giá trị rỗng/null bằng False trong Python. Nên "chưa có email" là ('email','=',False), "đã có email" là ('email','!=',False). Đừng dùng '' hay None.
3. Nhiều điều kiện = AND ngầm
Đặt nhiều bộ ba cạnh nhau trong list, chúng nối bằng VÀ:
# Công ty VÀ có email VÀ id > 10
[('is_company','=',True), ('email','!=',False), ('id','>',10)]
Muốn HOẶC hay phủ định thì cần toán tử tiền tố |, ! — đó là nội dung bài sau.
4. Xuyên quan hệ bằng dấu chấm
Lọc theo trường của bản ghi liên kết bằng dấu chấm, sâu bao nhiêu tầng cũng được:
[('country_id.code', '=', 'VN')] # quốc gia của đối tác có mã VN
[('order_id.partner_id.name', 'ilike', 'cà phê')] # xuyên 2 tầng
Odoo tự dịch thành JOIN phía SQL. Rất mạnh, nhưng xuyên quá sâu thì truy vấn nặng — cân nhắc.
Domain viết ở đâu?
Không chỉ trong code Python. Cùng một cú pháp domain xuất hiện ở:
- Record Rules (
[('user_id','=',user.id)]) — đã gặp. - View (
domaintrên trường Many2one để lọc lựa chọn). - Action (lọc sẵn dữ liệu khi mở menu).
- Bộ lọc tìm kiếm trên giao diện.
Học một lần, dùng khắp nơi.
Nhớ ba ý
- Domain là list các bộ ba
(field, toán_tử, value); nhiều bộ ba nối bằng AND ngầm;[]là lọc tất cả. ilikekhông phân biệt hoa thường (gần như luôn dùng để tìm chuỗi); trường trống dùng= False— đo thậtilike 'minh'=3 cònlike 'minh'=0.- Dấu chấm xuyên quan hệ (
country_id.code) để lọc theo trường của bản ghi liên kết; cùng cú pháp domain dùng ở record rules, view, action.
Đã nắm domain cơ bản với AND ngầm, giờ tới lúc diễn đạt điều kiện phức tạp hơn. Phần sau đào sâu domain nâng cao: toán tử tiền tố &, |, ! và cách lồng chúng để viết "HOẶC", phủ định, và điều kiện nhiều nhánh.