Phần trước ta thêm một ô "Thẻ thành viên" vào trang /my, dẫn tới /my/the. Giờ dựng chính trang đó: một danh sách bản ghi của khách trong portal, có phân trang, có sắp xếp, và — quan trọng nhất — chỉ hiện dữ liệu của người đang đăng nhập. Odoo cho sẵn các mảnh ghép: hàm portal_pager để phân trang, template portal.portal_table và portal.portal_searchbar để khỏi tự vẽ bảng và thanh sắp xếp. Bài này ráp chúng lại thành route /my/the hoàn chỉnh và chụp kết quả thật.
Route liệt kê: bốn việc cần làm
Một route danh sách portal luôn theo cùng một khuôn: (1) dựng miền lọc theo khách, (2) đếm tổng để phân trang, (3) gọi portal_pager, (4) search với limit/offset từ pager rồi render.

Hình 1: Python (trên) — mấu chốt lại là domain = [('partner_id','=', user.partner_id.id)]: chỉ thẻ của khách này. portal_pager tính sẵn offset, page_count, danh sách số trang; ta chỉ việc search với limit/offset. XML (dưới) — t-call portal.portal_layout cho khung portal, portal.portal_searchbar cho thanh sắp xếp, portal.portal_table cho bảng kèm pager. Không tự viết pager hay bảng.
portal_pager: phân trang trong một dòng
portal_pager (nhập from odoo.addons.portal.controllers.portal import pager as portal_pager) nhận url, total, page, step và trả về một dict có sẵn mọi thứ template cần:
pager = portal_pager(url='/my/the', total=total, page=page,
step=self._items_per_page, url_args={'sortby': sortby})
the_list = The.search(domain, limit=self._items_per_page, offset=pager['offset'])
pager['offset']— bỏ qua bao nhiêu bản ghi cho trang hiện tại (dùng thẳng chosearch).pager['page_count'],pager['pages']— số trang và danh sách nút để template vẽ.url_args— giữ lại tham số khác (nhưsortby) khi bấm sang trang khác, để không mất lựa chọn sắp xếp.
Route khai hai đường dẫn — /my/the và /my/the/page/<int:page> — để URL trang 2 đẹp là /my/the/page/2.
Kết quả thật: bảng + pager
Chạy thật với _items_per_page = 3, một khách có 4 thẻ sẽ thấy 3 dòng ở trang 1 và một pager "1 2":

Hình 2: Trang /my/the thật. Bảng do portal.portal_table vẽ (kèm sọc, kẻ dòng), dữ liệu sắp theo diem desc — VIP-0003 (150), VIP-0001 (150), VIP-0002 (85). Pager "1 2" ở dưới do portal_pager sinh; bấm 2 đi tới /my/the/page/2 xem thẻ còn lại. Tất cả là thẻ của chính khách đang đăng nhập.
searchbar_sortings: cho khách tự đổi thứ tự
Dict searchbar_sortings khai các kiểu sắp xếp; portal.portal_searchbar biến nó thành một menu thả xuống trên giao diện:
searchbar_sortings = {
'diem': {'label': 'Điểm cao nhất', 'order': 'diem desc'},
'name': {'label': 'Tên thẻ', 'order': 'name'},
}
sortby = sortby or 'diem'
order = searchbar_sortings[sortby]['order']
Khách chọn "Tên thẻ", URL thành /my/the?sortby=name, route đọc sortby, lấy order tương ứng, search sắp lại. Nhờ url_args={'sortby': sortby} trong portal_pager, lựa chọn này được giữ khi chuyển trang. Cùng cơ chế này còn có searchbar_filters (lọc) và searchbar_groupby (nhóm) nếu cần.
Vài lưu ý
- Miền lọc là hàng rào bảo mật, không phải chuyện hiển thị. Quên
partner_idlà khách này thấy thẻ khách khác. Với dữ liệu nhạy cảm, cân nhắc thêmsudo()có kiểm soát hoặc dựa vào Record Rules portal. limit/offsetphải khớp pager. Dùngpager['offset']vàstep = _items_per_page— tự tính tay dễ lệch, trang cuối thiếu/thừa dòng.- Giữ tham số qua
url_args. Thiếu nó, bấm sang trang 2 là mất luôn kiểu sắp xếp/bộ lọc. - Lưu lịch sử để điều hướng. Các module Odoo lưu
request.session['..._history'] = ids[:100]để trang chi tiết có nút "trước/sau"; làm theo nếu bạn có trang chi tiết cho từng thẻ.
Ba ý mang về
- Route danh sách portal theo khuôn 4 bước: miền lọc theo
partner_id→search_count→portal_pager→searchvớilimit/offsettừ pager; khai cả/my/thevà/my/the/page/<int:page>. - Dùng lại
portal.portal_table+portal.portal_searchbarthay vì tự vẽ — có sẵn bảng, pager, menu sắp xếp;searchbar_sortingscho khách đổi thứ tự và giữ được quaurl_args. - Miền
partner_id = user.partner_idlà bảo mật cốt lõi của portal — mỗi khách chỉ thấy bản ghi của mình; đừng để hở.
Ta đã cho khách xem dữ liệu của họ. Chiều ngược lại cũng quan trọng: cho khách gửi dữ liệu vào. Phần sau làm website form nhận dữ liệu từ khách — dựng biểu mẫu công khai, nhận POST, tạo bản ghi, và chống spam/bảo mật khi mở một form ra Internet.