This commit is contained in:
Cédric Lombion 2026-10-13 12:16:41 +02:00 • committed by GitHub
commit 0f2702a657
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 40 additions and 2 deletions

View file

@ -2146,8 +2146,15 @@ async def table_view_data(
if _next:
sort_value = None
if is_view:
# _next is an offset
offset = f" offset {int(_next)}"
# _next is an offset. A negative one starts from the first row, as a
# negative keyset token does for a table, and pagination continues
# from there.
try:
offset_value = max(int(_next), 0)
except ValueError:
raise BadRequest("_next must be an integer")
_next = str(offset_value)
offset = f" offset {offset_value}"
else:
components = urlsafe_components(_next)
# If a sort order is applied and there are multiple components,

View file

@ -355,6 +355,37 @@ async def test_validate_page_size(ds_client, path, expected_error):
assert response.status_code == 400
@pytest.mark.asyncio
@pytest.mark.parametrize(
"next_value",
(
"dog",
"1e3",
# A facet link whose "&sect" a client decoded as an HTML entity
"25%C2%A7or_name%3DOil",
),
)
async def test_validate_view_next(ds_client, next_value):
# Views paginate by offset, so _next has to be an integer
response = await ds_client.get(f"/fixtures/paginated_view.json?_next={next_value}")
assert response.status_code == 400
assert response.json()["error"] == "_next must be an integer"
@pytest.mark.asyncio
@pytest.mark.parametrize("next_value", ("-2", "-5", "-10"))
async def test_view_negative_next_starts_from_first_row(ds_client, next_value):
# As for a table, a negative _next starts from the first row and the
# next link continues the pagination from there
negative = await ds_client.get(
f"/fixtures/paginated_view.json?_size=5&_next={next_value}"
)
first = await ds_client.get("/fixtures/paginated_view.json?_size=5")
assert negative.status_code == 200
assert negative.json()["rows"] == first.json()["rows"]
assert negative.json()["next"] == first.json()["next"] == "5"
@pytest.mark.asyncio
async def test_page_size_zero(ds_client):
"""For _size=0 we return the counts, empty rows and no continuation token"""