From 4874c292860c7ad67da2a730d6e58dde2718adda Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 23:59:44 +0000 Subject: [PATCH] Remove the next_url extra - the key is always present next_url became a default table JSON key alongside next, making the extra a no-op. Requesting ?_extra=next_url now returns the standard unknown-extra 400 error. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ --- datasette/views/table.py | 6 +++++- datasette/views/table_extras.py | 17 ----------------- docs/json_api.rst | 13 +------------ docs/template_context.rst | 2 +- tests/test_api.py | 2 +- tests/test_error_shape.py | 8 ++++++++ tests/test_table_api.py | 18 +++++++----------- 7 files changed, 23 insertions(+), 43 deletions(-) diff --git a/datasette/views/table.py b/datasette/views/table.py index 8ce4b711..f7edd744 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -107,7 +107,6 @@ class TableContext(Context): human_description_en: str = from_extra() is_view: bool = from_extra() metadata: dict = from_extra() - next_url: str = from_extra() primary_keys: list = from_extra() private: bool = from_extra() query: dict = from_extra() @@ -124,6 +123,11 @@ class TableContext(Context): metadata={"help": "True if the data for this page was retrieved without errors"} ) next: str = field(metadata={"help": "Pagination token for the next page, or None"}) + next_url: str = field( + metadata={ + "help": "Full URL for the next page of results, or None if there are no more pages. See :ref:`json_api_pagination`." + } + ) count_truncated: bool = field( metadata={ "help": "True if ``count`` is a capped lower bound rather than an exact total, because Datasette stopped counting after its configured row-count limit." diff --git a/datasette/views/table_extras.py b/datasette/views/table_extras.py index e36e8161..50002d92 100644 --- a/datasette/views/table_extras.py +++ b/datasette/views/table_extras.py @@ -321,21 +321,6 @@ class HumanDescriptionEnExtra(Extra): return human_description_en -class NextUrlExtra(Extra): - description = "Full URL for the next page of results" - example = ExtraExample( - "/fixtures/facetable.json?_size=1&_extra=next_url", - note=( - "``null`` if there are no more pages of results. " - "See :ref:`json_api_pagination`." - ), - ) - scopes = {ExtraScope.TABLE} - - async def resolve(self, context): - return context.next_url - - class ColumnsExtra(Extra): description = "List of column names returned by this table, row or query." example = ExtraExample("/fixtures/facetable.json?_extra=columns") @@ -1250,7 +1235,6 @@ TABLE_EXTRA_BUNDLES = { "count", "count_sql", "human_description_en", - "next_url", "metadata", "query", "columns", @@ -1286,7 +1270,6 @@ TABLE_EXTRA_CLASSES = [ SuggestedFacetsExtra, FacetInstancesProvider, HumanDescriptionEnExtra, - NextUrlExtra, ColumnsExtra, AllColumnsExtra, PrimaryKeysExtra, diff --git a/docs/json_api.rst b/docs/json_api.rst index 893af634..ec60a3a9 100644 --- a/docs/json_api.rst +++ b/docs/json_api.rst @@ -333,7 +333,7 @@ These can be repeated or comma-separated: :: - ?_extra=columns&_extra=count,next_url + ?_extra=columns&_extra=count,count_sql Requesting an ``_extra`` name that does not exist returns a ``400`` error in the :ref:`standard error format `, for example ``{"ok": false, "error": "Unknown _extra: nope", ...}``. @@ -437,17 +437,6 @@ The available table extras are listed below. "where state = \"CA\" sorted by pk" -``next_url`` - Full URL for the next page of results - - ``GET /fixtures/facetable.json?_size=1&_extra=next_url`` - - ``null`` if there are no more pages of results. See :ref:`json_api_pagination`. - - .. code-block:: json - - "http://localhost/fixtures/facetable.json?_size=1&_extra=next_url&_next=1" - ``columns`` List of column names returned by this table, row or query. diff --git a/docs/template_context.rst b/docs/template_context.rst index e9447058..e445b335 100644 --- a/docs/template_context.rst +++ b/docs/template_context.rst @@ -329,7 +329,7 @@ Many of these keys are shared with the :ref:`JSON API ` for this page. Pagination token for the next page, or None ``next_url`` - ``str`` - Full URL for the next page of results + Full URL for the next page of results, or None if there are no more pages. See :ref:`json_api_pagination`. ``ok`` - ``bool`` True if the data for this page was retrieved without errors diff --git a/tests/test_api.py b/tests/test_api.py index 9a96f14f..a15a507c 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -722,7 +722,7 @@ def test_config_cache_size(app_client_larger_cache_size): def test_config_force_https_urls(): with make_app_client(settings={"force_https_urls": True}) as client: response = client.get( - "/fixtures/facetable.json?_size=3&_facet=state&_extra=next_url,suggested_facets" + "/fixtures/facetable.json?_size=3&_facet=state&_extra=suggested_facets" ) assert response.json["next_url"].startswith("https://") assert response.json["facet_results"]["results"]["state"]["results"][0][ diff --git a/tests/test_error_shape.py b/tests/test_error_shape.py index 44856b36..768814fd 100644 --- a/tests/test_error_shape.py +++ b/tests/test_error_shape.py @@ -739,3 +739,11 @@ async def test_sql_interrupted_html_page_keeps_rich_error(ds_client): ) assert response.status_code == 400 assert "