diff --git a/datasette/views/table.py b/datasette/views/table.py index b28d6060..96e8922b 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -402,8 +402,8 @@ class TableView(RowTableShared): ) # Allow for custom sort order - sort = special_args.get("_sort") - sort_desc = special_args.get("_sort_desc") + sort = special_args.get("_sort") or table_metadata.get("sort") + sort_desc = special_args.get("_sort_desc") or table_metadata.get("sort_desc") if sort and sort_desc: raise DatasetteError("Cannot use _sort and _sort_desc at the same time") diff --git a/docs/metadata.rst b/docs/metadata.rst index 5d9155ea..54008550 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -109,6 +109,39 @@ registered with Pint:: .. _unit registry: https://github.com/hgrecco/pint/blob/master/pint/default_en.txt .. _custom units: http://pint.readthedocs.io/en/latest/defining.html +.. _metadata_default_sort: + +Setting a default sort order +---------------------------- + +By default Datasette tables are sorted by primary key. You can over-ride this default for a specific table using the ``"sort"`` or ``"sort_desc"`` metadata properties:: + + { + "databases": { + "mydatabase": { + "tables": { + "example_table": { + "sort": "created" + } + } + } + } + } + +Or use ``"sort_desc"`` to sort in descending order:: + + { + "databases": { + "mydatabase": { + "tables": { + "example_table": { + "sort_desc": "created" + } + } + } + } + } + .. _metadata_sortable_columns: Setting which columns can be used for sorting diff --git a/tests/fixtures.py b/tests/fixtures.py index 0c1b10a0..5cc64a16 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -304,6 +304,8 @@ METADATA = { "fts_table": "searchable_fts", "fts_pk": "pk", }, + "attraction_characteristic": {"sort_desc": "pk"}, + "facet_cities": {"sort": "name"}, }, "queries": { "𝐜𝐢𝐭𝐢𝐞𝐬": "select id, name from facet_cities order by id limit 1;", diff --git a/tests/test_html.py b/tests/test_html.py index 86880cfd..a0216672 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -1095,3 +1095,51 @@ def test_config_template_debug_off(app_client): response = app_client.get("/fixtures/facetable?_context=1") assert response.status == 200 assert not response.text.startswith("
{")
+
+
+def test_metadata_sort(app_client):
+ response = app_client.get("/fixtures/facet_cities")
+ assert response.status == 200
+ table = Soup(response.body, "html.parser").find("table")
+ assert table["class"] == ["rows-and-columns"]
+ ths = table.findAll("th")
+ assert ["id", "name\xa0▼"] == [th.find("a").string.strip() for th in ths]
+ rows = [[str(td) for td in tr.select("td")] for tr in table.select("tbody tr")]
+ assert [
+ [
+ '3 ',
+ 'Detroit ',
+ ],
+ [
+ '2 ',
+ 'Los Angeles ',
+ ],
+ [
+ '4 ',
+ 'Memnonia ',
+ ],
+ [
+ '1 ',
+ 'San Francisco ',
+ ],
+ ] == rows
+
+
+def test_metadata_sort_desc(app_client):
+ response = app_client.get("/fixtures/attraction_characteristic")
+ assert response.status == 200
+ table = Soup(response.body, "html.parser").find("table")
+ assert table["class"] == ["rows-and-columns"]
+ ths = table.findAll("th")
+ assert ["pk\xa0▲", "name"] == [th.find("a").string.strip() for th in ths]
+ rows = [[str(td) for td in tr.select("td")] for tr in table.select("tbody tr")]
+ assert [
+ [
+ '2 ',
+ 'Paranormal ',
+ ],
+ [
+ '1 ',
+ 'Museum ',
+ ],
+ ] == rows