Ở bài website ta viết t-call="website.layout" để mượn cả header/footer của site. Đó chính là t-call — công cụ tái sử dụng template của QWeb. Thay vì chép đi chép lại một khối HTML, bạn viết nó một lần thành template riêng rồi gọi ở mọi nơi cần. Bài này mổ t-call kỹ hơn, gồm cả cái khe kỳ lạ t-out="0" mà website.layout dùng để "bọc" nội dung của bạn.
t-call gọi một template khác vào chỗ đó
<t t-call="module.template"/> chèn (include) nội dung của template được nêu vào đúng vị trí đó. Điểm mấu chốt: template được gọi thấy cùng context với chỗ gọi — mọi biến đang có (kể cả biến vòng lặp) đều dùng được bên trong nó. Nhờ vậy bạn tách một "mảnh dùng chung" ra template riêng, rồi gọi lại với dữ liệu khác nhau mỗi lần.
Mình dựng ba template minh hoạ đủ ba kiểu dùng:

Hình 1: Ba template. (1) the_card — mảnh dùng lại, vẽ một thẻ, đọc biến the. (2) khung_vien — một cái khung có khe: t-out="0" là chỗ nội dung con của lời gọi sẽ rơi vào. (3) trang — gọi website.layout, rồi bên trong gọi khung_vien (bọc), và trong vòng t-foreach gọi the_card cho mỗi thẻ. the_card thấy biến the vì template được gọi dùng chung context với chỗ gọi.
Cái khe số 0
Đây là phần hay bị bối rối. Khi bạn viết t-call có nội dung con:
<t t-call="quan_ca_phe.khung_vien">
...nội dung này...
</t>
thì "nội dung này" không mất đi — nó được gói lại và truyền vào template khung_vien dưới cái tên đặc biệt 0. Trong khung_vien, <t t-out="0"/> chính là chỗ "đổ" nội dung đó ra. Đó là cách một template bọc thứ khác: website.layout cũng làm y hệt — nội dung trang của bạn rơi vào khe 0 của nó, giữa header và footer.
Nói gọn: t-call không có body → chỉ include; t-call có body → include và truyền body vào khe 0 để template kia đặt vào đâu tuỳ ý.
Kết quả thật
Trang /the-tcall render ra: một khung viền nâu (do khung_vien bọc qua khe 0), bên trong là bốn thẻ, mỗi thẻ do the_card dựng:

Hình 2: Kết quả thật. Khung viền nâu là khung_vien — nội dung (bốn thẻ) được truyền vào qua khe 0. Bốn thẻ đều cùng kiểu dáng vì cùng gọi the_card; mình chỉ viết template thẻ một lần. Vòng t-foreach đặt biến the cho mỗi vòng, the_card đọc đúng the đó — VIP-0003 Vàng 150, VIP-0001 Bạc 150, VIP-0002 85, VIP-0004 0.
Muốn đổi kiểu thẻ (thêm icon, đổi bố cục)? Sửa một template the_card, cả bốn (và mọi trang khác gọi nó) đổi theo. Đó là giá trị của việc tách ra.
Vài lưu ý
- Template con dùng chung context — tiện nhưng cũng dễ vô tình phụ thuộc biến của nơi gọi. Muốn rõ ràng, đặt biến trước bằng
t-set(hoặc truyền vào khe0) thay vì ngầm dựa vào tên biến trùng. t-callkháct-call-assets. Cái sau nạp một bundle asset (JS/CSS) vào trang, không phải chèn template — đừng lẫn.t-callcó ở cả ba loại QWeb (OWL, report, website). Cùng ý tưởng tái sử dụng, chỉ khác nơi chạy.t-out="0"mới là cách nhận body;t-out="0"render nội dung đã được QWeb dựng sẵn (markup), kháct-escmột chuỗi thường.
Ba ý mang về
t-call="module.template"chèn một template vào chỗ đó và cho nó dùng chung context — tách một mảnh HTML dùng nhiều lần (một card, một khối macro) ra template riêng rồi gọi lại khắp nơi.- Nội dung con của
t-callrơi vào khe đặc biệt0; template được gọi đặt nó ra bằngt-out="0". Đây là cách một template bọc thứ khác — chínhwebsite.layouthoạt động như vậy. - Sửa một template dùng chung, mọi nơi gọi nó đổi theo. Đó là lý do tách ra: một nguồn sự thật cho phần lặp lại, thay vì chép HTML rồi sửa sót.
Trong the_card ta viết t-esc="the.name" — đọc field thô. Nhưng Odoo còn một directive hiểu kiểu của field và tự định dạng: phần sau nói về t-field — hiển thị dữ liệu bản ghi đúng định dạng, có thể sửa tại chỗ trên website, khác t-esc/t-out ở đâu.