• 
      

    Add base support for keyset pagination.

    Review Request #15274 — Created Sept. 4, 2026 and updated — Latest diff uploaded

    Information

    Djblets
    release-7.x

    Reviewers

    Django's database paginators work by tracking what page you're in and
    generating new SQL using OFFSET and LIMIT to select the right page
    of results to return. This has a major performance impact the further in
    you go, since the database often has to fetch the values first before
    calculating the offset into it. With heavy usage and deep lists of
    pages, this gets expensive fast.

    Keyset pagination is an alternative approach that replaces page-based
    offsets with "cursors". A cursor is a representation of a filter query
    that selects all entries before or after the current page of results.
    This involves selecting using sortable criteria (such as a timestamp)
    along with a "PK tie-breaker" (using a sortable row ID as the last
    criteria in case the rows otherwise match), and a query that's sorted in
    the same direction.

    With this in place, the paginator can encode a cursor that says (for
    example), "Select results after this last result's timestamp and PK."
    Or when traversing backwards, "Select results before his first result's
    timestamp and PK."

    There are some tradeoffs. You can't jump to arbitrary pages (though
    there's a trick here) and you can't effectively get the full result
    count (as that can have the same expense that pagination has for
    filtered results). This usually leads to UIs that just have "Previous"
    and "Next" buttons.

    The trick to jumping to page numbers is to precompute some number of
    pages in advance in either direction within the initial query. This
    makes it easy to generate a series of cursors based off of that data in
    order for the UI to provide the next few page numbers. This is fairly
    cheap, especially in cases like the datagrid where the query is fetching
    just PKs or other cheap columns and then following up with a full data
    fetch.

    This change implements the base support for all this. Datagrid and API
    usage will follow.

    Unit tests pass.

    Made use of this in an upcoming change for datagrids.

    Commits

    Files