Ở bài trước ta sửa cấu trúc view bằng code — mạnh nhưng nặng. Nhưng phần lớn nhu cầu "view cư xử khác nhau tuỳ chỗ mở" không cần đụng cấu trúc: chỉ cần truyền vài giá trị. Kênh đó là context — một cuốn từ điển đi kèm mọi action, chảy vào view và code. Một menu "Cấp thẻ Vàng" có thể mở form đã điền sẵn hạng Vàng, 100 điểm; một menu "Đơn của tôi" mở list đã lọc sẵn đơn của mình — tất cả nhờ context, không cần form/list riêng. Bài này cho một form tự điền sẵn để thấy context làm việc.
Đặt context trên action
<record id="action_the_vang" model="ir.actions.act_window">
<field name="res_model">quan.the.thanh.vien</field>
<field name="context">{
'default_hang_the': 'vang', <!-- điền sẵn khi TẠO MỚI -->
'default_trang_thai': 'dang_dung',
'default_diem': 100,
'search_default_vip': 1, <!-- bật filter 'vip' sẵn -->
}</field>
</record>

Hình 1: context là một dict trên action. Các khoá "phép thuật" Odoo hiểu sẵn: default_<field> đặt giá trị mặc định của field khi tạo bản ghi mới; search_default_<filter> bật sẵn một filter/group của search view (đã gặp ở bài search view); form_view_ref/list_view_ref ép dùng một view cụ thể. Ngoài ra bạn tự đặt cờ tuỳ ý rồi đọc bằng self.env.context.get(...) trong code.
Xem thật: form mở ra đã điền sẵn
Gắn context trên vào một action "Cấp thẻ Vàng", bấm Tạo mới — form mở ra đã có giá trị:

Hình 2: Form tạo mới, tự điền sẵn nhờ context. Hạng thẻ = Vàng (default_hang_the), Điểm tích luỹ = 100% (default_diem), statusbar = Đang dùng (default_trang_thai) — tất cả đã có mà người dùng chưa gõ gì. Vì là hạng Vàng nên ô "Ghi chú nội bộ" cũng hiện (nhớ bài invisible điều kiện). Người dùng chỉ cần điền tên khách và lưu — nhanh hơn hẳn.
Điểm hay: cùng một model, cùng một form, nhưng mở qua action khác nhau cho trải nghiệm khác nhau. Một action "Cấp thẻ Bạc" chỉ cần đổi default_hang_the: 'bac' là xong — không cần form riêng.
default_get đọc context ra sao
Cơ chế bên dưới: khi tạo bản ghi mới, Odoo gọi default_get, và mỗi khoá default_<field> trong context thành giá trị mặc định của field đó. Kiểm chứng thật:
M = env['quan.the.thanh.vien'].with_context(
default_hang_the='vang', default_diem=100, default_trang_thai='dang_dung')
M.default_get(['hang_the', 'diem', 'trang_thai'])
# → {'hang_the': 'vang', 'diem': 100, 'trang_thai': 'dang_dung'}
Đây là lý do default_ chỉ ảnh hưởng bản ghi mới — nó đi qua default_get, vốn chỉ chạy khi tạo.
Các dùng context hay gặp
default_<field>: điền sẵn khi tạo — cho menu chuyên biệt ("Cấp thẻ Vàng", "Đơn nháp").search_default_<filter>/search_default_<groupby>: mở màn hình đã lọc/nhóm sẵn ("Đơn của tôi", "Việc quá hạn").default_<x2m>: điền sẵn dòng con qua lệnhCommand(ví dụ[(0,0,{...})]).- Cờ tuỳ biến: đặt
{'from_special_flow': True}rồi đọcself.env.context.get('from_special_flow')trongcreate/write/compute để đổi hành vi theo ngữ cảnh. - Trên
<field>Many2one/x2many:context="{'default_x': ...}"truyền xuống form con khi mở/tạo bản ghi liên quan.
Vài lưu ý Odoo 19
- context là dict "cộng dồn" — action, view, và code chồng khoá lên nhau; khoá sau ghi đè khoá trước. Dùng
with_context(...)để thêm mà không mất khoá cũ. default_chỉ chạy lúc tạo (quadefault_get); muốn ép giá trị khi sửa thì phải làm trongwrite/onchange, không phải context.- Đừng nhét dữ liệu lớn vào context — nó đi kèm mọi request, giữ nhẹ (id, cờ, giá trị nhỏ).
- Cờ tuỳ biến nên có tiền tố module (
quan_ca_phe_...) để tránh đụng khoá của app khác.
Ba ý mang về
contextcủa action là kênh nhẹ đổi hành vi view mà không đụng cấu trúc:default_<field>điền sẵn khi tạo,search_default_<filter>bật lọc/nhóm sẵn,form_view_refép view. Đã chứng minh: action "Cấp thẻ Vàng" mở form đã điền Vàng/100/Đang dùng.default_đi quadefault_getnên chỉ tác động bản ghi mới (kiểm chứng:default_gettrả đúng giá trị context); muốn ép khi sửa phải dùngwrite/onchange.- Đặt cờ tuỳ biến trong context rồi đọc
self.env.context.get(...)để đổi hành vi theo ngữ cảnh; truyền context xuống form con quacontexttrên field Many2one/x2many. Giữ context nhẹ, đặt tiền tố cho cờ riêng.
Nhắc tới search_default và lọc/nhóm, lần sau ta đào sâu chính chuyện sắp xếp và gom nhóm dữ liệu trong bảng: Phần sau mổ xẻ sắp xếp và nhóm trên list view — default_order, _order của model, nhóm nhiều cấp, và cách chúng phối hợp.