Ở bài trước ta viết trường computed. Có một tham số nhỏ trên đó quyết định rất nhiều: store. Nó là ranh giới giữa "trường tính lại mỗi lần đọc" và "trường lưu hẳn xuống cơ sở dữ liệu". Chọn sai là hoặc trang chậm, hoặc không tìm kiếm/sắp xếp được. Bài này mổ xẻ đánh đổi đó.
Hai chế độ, một tham số
- Không store (mặc định): trường computed tính lại mỗi lần đọc, không có cột trong bảng SQL. Không tốn chỗ lưu, không tốn gì khi ghi.
store=True: giá trị được lưu xuống CSDL (có cột thật), Odoo tính lại và ghi khi trường nguồn (@api.depends) đổi. Đọc nhanh, tìm kiếm/sắp xếp được — đổi lại tốn chỗ và tốn khi ghi.

Hình 1: Đánh đổi. store=True cho bạn cột SQL → tìm kiếm, sắp xếp, read_group đều được, và đọc nhanh (không tính lại). Không store thì nhẹ khi ghi nhưng không lọc/sắp bằng SQL (trừ khi tự viết hàm search). Quy tắc: cần tìm/sắp/báo cáo theo trường → store=True; chỉ hiển thị → để không store.
Bằng chứng thật
Đây là output thật trên db blog19 cho thấy khác biệt rõ ràng:

Hình 2: Bằng chứng thật. amount_total (compute + store=True) có cột thật trong bảng sale_order (kiểm bằng information_schema), nên search([('amount_total','>',1000000)], order='amount_total desc') chạy ngon, trả về các đơn lớn nhất. Còn trường computed không store như activity_exception_icon thì search theo nó nổ ValueError: Cannot convert ... to SQL — vì không có cột để lọc.
Khi nào dùng store=True
Chọn store=True khi bạn cần ít nhất một trong các điều này:
- Tìm kiếm theo trường (bộ lọc trên giao diện, domain).
- Sắp xếp danh sách theo trường.
- Gom nhóm/báo cáo (
read_group, pivot, biểu đồ). - Đọc rất thường xuyên trên bảng lớn (đọc sẵn nhanh hơn tính lại).
Ví dụ điển hình: amount_total phải store=True vì báo cáo doanh thu gom nhóm theo nó (nhớ read_group).
Khi nào để KHÔNG store
- Trường chỉ hiển thị trên form, không lọc/sắp (ví dụ một chuỗi ghép để show).
- Giá trị phụ thuộc ngữ cảnh (người dùng, công ty hiện tại) — lưu xuống là sai cho người khác.
- Trường đổi liên tục mà ít khi cần tìm — lưu chỉ tổ tốn ghi.
Cái giá của store=True
store=True không miễn phí:
- Tốn chỗ: thêm một cột dữ liệu.
- Tốn khi ghi: mỗi lần trường nguồn đổi, Odoo tính lại và ghi xuống CSDL — với bảng lớn và
@api.dependsxuyên nhiều bản ghi, việc này có thể nặng. - Rủi ro lệch: nếu
@api.dependskhai thiếu, giá trị lưu sẽ cũ mà không ai biết (không store thì luôn tính mới nên không lệch). Đây là lý do@api.dependsđủ và đúng càng quan trọng khistore=True.
Nạp lại giá trị lưu (recompute)
Khi bạn sửa công thức của một trường store=True, giá trị cũ trong CSDL không tự đổi. Cần nâng cấp module để Odoo tính lại:
odoo -d blog19 -u ten_module --stop-after-init
Hoặc trong dev, gọi Model._recompute_fields() / cập nhật qua giao diện kỹ thuật.
Nhớ ba ý
store=Truelưu trường computed xuống CSDL (có cột SQL) → tìm kiếm, sắp xếp,read_groupđược; không store thì tính mỗi lần đọc, không lọc SQL được (đo thật: search choValueError: Cannot convert to SQL).- Chọn
store=Truekhi cần tìm/sắp/báo cáo hoặc đọc nhiều trên bảng lớn; để không store khi chỉ hiển thị hoặc giá trị phụ thuộc ngữ cảnh. store=Truetốn chỗ + ghi, và rủi ro lệch nếu@api.dependskhai thiếu; sửa công thức thì phải-u moduleđể tính lại giá trị đã lưu.
Trường computed lưu được rồi, có một loại trường "tính toán" đặc biệt gọn hơn: related. Phần sau khám phá trường related — rút gọn một chuỗi quan hệ (partner_id.country_id.name) thành một trường phẳng, mà không cần viết hàm compute.