Exclude unsortable primary key from sort menu, refs #1980

When a table configures sortable_columns and omits the primary key, the
sort dropdown still offered it. display_columns_and_rows() rebuilds the
primary key as the leading link column and hardcoded its "sortable" flag
to len(pks) == 1 instead of consulting sortable_columns, so selecting it
produced a 500/400 "Cannot sort table by id" error.

The flag now checks sortable_columns like every other column.

Adds tests/test_table_html.py::test_sort_menu_excludes_unsortable_primary_key.
This commit is contained in:
Sanjay Santhanam 2026-07-25 15:55:42 -07:00
commit 4f35b0c1d0
2 changed files with 32 additions and 1 deletions

View file

@ -901,7 +901,7 @@ async def display_columns_and_rows(
columns = [col for col in columns if col["name"] != pks[0]]
first_column = {
"name": pks[0],
"sortable": len(pks) == 1,
"sortable": pks[0] in sortable_columns,
"is_pk": True,
"type": column_details[pks[0]].type,
"notnull": column_details[pks[0]].notnull,

View file

@ -397,6 +397,37 @@ async def test_sort_links(ds_client):
]
@pytest.mark.asyncio
async def test_sort_menu_excludes_unsortable_primary_key():
# https://github.com/simonw/datasette/issues/1980
ds = Datasette(
[],
metadata={
"databases": {
"data": {"tables": {"timezones": {"sortable_columns": ["tzid"]}}}
}
},
)
try:
db = ds.add_database(
Database(ds, memory_name="test_sort_menu_unsortable_pk"), name="data"
)
await db.execute_write_script("""
create table timezones (
id integer primary key,
tzid text
);
insert into timezones (id, tzid) values (133, 'Europe/London');
""")
response = await ds.client.get("/data/timezones")
assert response.status_code == 200
select = Soup(response.text, "html.parser").find("select", {"name": "_sort"})
options = [option["value"] for option in select.find_all("option")]
assert options == ["", "tzid"]
finally:
ds.close()
@pytest.mark.asyncio
async def test_facet_display(ds_client):
response = await ds_client.get(