DataTableMixin — sortable, filterable, paginated grid
Backed by the realtime.Order model from PR #1. Click a column header to sort. Use the search box to filter. Prev/next to page. All wired automatically by the mixin.
Orders
DataTableMixin| # | Customer | Total ($) | Status | Created |
|---|---|---|---|---|
| 17 | Acme #4 | 79.96 | pending | 2026-05-03T21:56:31.966607+00:00 |
| 16 | Demo customer #16 | 319.84 | pending | 2026-05-03T21:56:24.912423+00:00 |
| 15 | Tyrell Corp | 159.92 | shipped | 2026-05-02T05:54:31.402197+00:00 |
| 14 | Cyberdyne | 139.93 | pending | 2026-05-02T05:54:31.399421+00:00 |
| 13 | Stark Industries | 119.94 | cancelled | 2026-05-02T05:54:31.396468+00:00 |
The whole pattern
from djust.components.mixins.data_table import DataTableMixin
class OrderDataTableView(DataTableMixin, LiveView):
table_model = Order
table_columns = [
{'key': 'customer', 'label': 'Customer', 'sortable': True, 'filterable': True},
{'key': 'total', 'label': 'Total', 'sortable': True},
{'key': 'status', 'label': 'Status', 'sortable': True, 'filterable': True},
]
table_page_size = 25
table_default_sort = '-created_at'
def mount(self, request, **kwargs):
super().mount(request, **kwargs)
self.init_table_state()
self.refresh_table()
The mixin auto-decorates on_table_sort / on_table_page /
on_table_filter with @event_handler(). The
template tag emits
the <table> with click-to-sort handlers wired to those events. No per-view
handler boilerplate.
# Customer Total ($) Status Created 17 Acme #4 79.96 pending 2026-05-03T21:56:31.966607+00:00 16 Demo customer #16 319.84 pending 2026-05-03T21:56:24.912423+00:00 15 Tyrell Corp 159.92 shipped 2026-05-02T05:54:31.402197+00:00 14 Cyberdyne 139.93 pending 2026-05-02T05:54:31.399421+00:00 13 Stark Industries 119.94 cancelled 2026-05-02T05:54:31.396468+00:00