Một khối trên trang website hiển thị "Top thành viên" hay "Sản phẩm mới nhất". Nếu bạn gõ cứng tên và số vào HTML, hôm sau dữ liệu đổi mà trang vẫn hiện số cũ — nội dung tĩnh. Snippet động thì khác: nó đọc thẳng model, nên mỗi lần tải trang là dữ liệu mới nhất. Bài này dựng một snippet "Bảng điểm sống" đọc quan.the.thanh.vien trực tiếp, rồi chứng minh nó sống bằng cách đổi một con số trong CSDL và tải lại — cùng nhìn website.snippet.filter, cơ chế chuẩn mà builder dùng.
Snippet động = QWeb truy vấn model khi render
Cách đơn giản và thật nhất: một template QWeb (một <section class="s_..."> — chính là hình dạng của mọi snippet) mà truy vấn model ngay trong lúc render, bằng request.env. QWeb website cho phép gọi ORM inline qua t-value; Odoo dùng đúng kiểu này trong các snippet lõi.

Hình 1: Snippet (trên) đặt the_list bằng request.env['quan.the.thanh.vien'].sudo().search([], order='diem desc') ngay trong template, rồi t-foreach vẽ từng thẻ. Vì t-value chạy lại mỗi lần render, dữ liệu luôn mới. Phần dưới là model website.snippet.filter — cách builder tích hợp sẵn (mục cuối bài).
Chứng minh "sống": before và after
Đây là điểm mấu chốt. Lần tải đầu, snippet hiển thị bốn thẻ theo điểm hiện tại:

Hình 2: Lần tải thứ nhất — VIP-0001 (150), VIP-0003 (150), VIP-0002 (85), VIP-0004 (0, đứng cuối). Tổng 385 điểm.
Giờ tôi đổi điểm VIP-0004 từ 0 lên 999 trong CSDL (qua ORM, không đụng gì tới trang), rồi tải lại cùng URL đó:

Hình 3: Tải lại cùng trang sau khi đổi CSDL — VIP-0004 nhảy lên 999 và đứng đầu (vì sắp theo diem desc), tổng thành 1384. Không sửa một dòng HTML nào; snippet tự truy vấn lại và sắp xếp theo dữ liệu mới. Đó là "sống".
Nếu là snippet tĩnh (gõ cứng "0"), trang vẫn hiện 0. Khác biệt nằm ở chỗ template hỏi model thay vì nhớ số.
Lưu ý khi dựng snippet động thủ công
sudo()có kiểm soát. Trang công khai chạy bằng Public user;sudo()để đọc, nhưng chỉ trả ra dữ liệu được phép công khai. Đừng vô tình lộ field nhạy cảm.- Giới hạn số bản ghi.
search(..., limit=N)— đừng để một snippetsearch([])kéo hàng nghìn bản ghi làm chậm trang. (Không phải ngẫu nhiênwebsite.snippet.filterchặnlimittrong khoảng 1–16.) - Cẩn thận cache. Odoo/trình duyệt có thể cache trang; khi test "sống" nhớ tải lại sạch cache. Với dữ liệu thay đổi liên tục, cân nhắc header cache phù hợp.
- Query nặng trong template làm chậm render. Truy vấn phức tạp nên tính ở controller/model rồi truyền vào, hơn là nhồi hết vào
t-value.
Cách chuẩn của builder: website.snippet.filter
Cách trên là "tự làm", đủ cho một khối cố định. Nhưng Odoo có hẳn một cơ chế để người quản trị tự cấu hình snippet động ngay trong trình dựng web, không cần code: website.snippet.filter.
Nhìn lõi: model này giữ field_names (những cột hiển thị), limit (1–16 bản ghi), và trỏ tới một ir.filter hoặc ir.actions.server để lấy bản ghi từ bất kỳ model nào. Nó có hàm _render(template_key, limit, search_domain, ...) mà snippet s_dynamic_snippet của website gọi để đổ dữ liệu vào. Nhờ vậy người dùng kéo snippet "Dynamic Snippet", chọn model/bộ lọc/số lượng trong bảng tùy chọn, và có ngay một khối động — dữ liệu do bạn khai một website.snippet.filter cung cấp.
Chọn cách nào: tự viết QWeb khi khối cố định, gắn liền module (như bảng điểm này); website.snippet.filter + s_dynamic_snippet khi muốn người vận hành tự đổi model/bộ lọc/kiểu hiển thị bằng chuột.
Ba ý mang về
- Snippet động đọc model khi render — một template QWeb (
<section class="s_...">) đặtt-value="request.env[...].search(...)"rồit-foreach; mỗi lần tải trang chạy lại truy vấn nên dữ liệu luôn mới (khác snippet tĩnh gõ cứng). - "Sống" nghĩa là đổi model → trang tự đổi: đổi điểm trong CSDL rồi tải lại cùng URL, snippet sắp lại và hiện số mới — không sửa HTML.
- Builder có
website.snippet.filter(field_names,limit1–16,_render) để người quản trị tự cấu hình snippet động quas_dynamic_snippet; tự viết QWeb cho khối cố định, dùng filter cho khối người dùng tự chỉnh.
Hết mảng website/controller, phần sau ta bước sang một khu chuyên biệt và rất hay dùng: Phần sau mổ xẻ eCommerce hook can thiệp giá sản phẩm — móc vào cách Odoo tính giá để áp khuyến mãi, giá theo nhóm khách, hay logic giá tùy biến của riêng bạn.