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
#CustomerTotal ($)StatusCreated
17Acme #479.96pending2026-05-03T21:56:31.966607+00:00
16Demo customer #16319.84pending2026-05-03T21:56:24.912423+00:00
15Tyrell Corp159.92shipped2026-05-02T05:54:31.402197+00:00
14Cyberdyne139.93pending2026-05-02T05:54:31.399421+00:00
13Stark Industries119.94cancelled2026-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

#CustomerTotal ($)StatusCreated
17Acme #479.96pending2026-05-03T21:56:31.966607+00:00
16Demo customer #16319.84pending2026-05-03T21:56:24.912423+00:00
15Tyrell Corp159.92shipped2026-05-02T05:54:31.402197+00:00
14Cyberdyne139.93pending2026-05-02T05:54:31.399421+00:00
13Stark Industries119.94cancelled2026-05-02T05:54:31.396468+00:00
template tag emits the <table> with click-to-sort handlers wired to those events. No per-view handler boilerplate.