Pass columns and rows to can_render for canned queries (#2711)

The HTML branch of QueryView built an empty data dict before looping
over register_output_renderer can_render callbacks, so renderers that
depend on the result columns or rows (e.g. datasette-atom,
datasette-ics) never appeared as export options for canned queries.
Populate data with the executed query's rows, columns, SQL and query
name.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Simon Willison 2026-06-10 23:30:12 -07:00
commit 154ea483ea
2 changed files with 34 additions and 1 deletions

View file

@ -762,7 +762,15 @@ class QueryView(View):
)
),
)
data = {}
data = {
"ok": query_error is None,
"rows": rows,
"columns": columns,
"query": {"sql": sql, "params": params},
"query_name": stored_query.name if stored_query else None,
"database": database,
"table": None,
}
headers.update(
{
"Link": '<{}>; rel="alternate"; type="application/json+datasette"'.format(

View file

@ -626,6 +626,31 @@ async def test_hook_register_output_renderer_can_render(ds_client):
}.items() <= ds_client.ds._can_render_saw.items()
@pytest.mark.asyncio
async def test_hook_register_output_renderer_can_render_canned_query(ds_client):
# https://github.com/simonw/datasette/issues/2711
# can_render for a canned query must be passed the query's columns, rows
# and SQL - previously it received an empty data dict, so renderers that
# depend on the columns (datasette-atom, datasette-ics) never showed up.
response = await ds_client.get("/fixtures/pragma_cache_size")
assert response.status_code == 200
saw = ds_client.ds._can_render_saw
assert saw["columns"] == ["cache_size"]
assert len(saw["rows"]) == 1
assert saw["sql"] == "PRAGMA cache_size;"
assert saw["query_name"] == "pragma_cache_size"
# The renderer's export link should therefore be offered
links = (
Soup(response.text, "html.parser")
.find("p", {"class": "export-links"})
.find_all("a")
)
actual = [link["href"] for link in links]
assert any(
href.startswith("/fixtures/pragma_cache_size.testall") for href in actual
)
@pytest.mark.asyncio
async def test_hook_prepare_jinja2_environment(ds_client):
ds_client.ds._HELLO = "HI"