From 236aa065b2ecfbe5a77870689bae432b89a48b23 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sat, 21 Mar 2020 19:28:35 -0700 Subject: [PATCH] "sort" and "sort_desc" metadata properties, closes #702 --- datasette/views/table.py | 4 ++-- docs/metadata.rst | 33 +++++++++++++++++++++++++++ tests/fixtures.py | 2 ++ tests/test_html.py | 48 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) 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