From 5629aaca67437acce8af47acb06488bd9991420b Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sun, 5 Aug 2018 17:29:23 -0700 Subject: [PATCH] sortable_columns also now works with views --- datasette/views/table.py | 3 ++- docs/metadata.rst | 17 +++++++++++++++++ tests/fixtures.py | 3 +++ tests/test_html.py | 37 ++++++++++++++++++++----------------- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/datasette/views/table.py b/datasette/views/table.py index ae71d33d..a3a2c3b7 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -352,7 +352,8 @@ class TableView(RowTableShared): sortable_columns = set() if not is_view: table_rows_count = table_info["count"] - sortable_columns = self.sortable_columns_for_table(name, table, use_rowid) + + sortable_columns = self.sortable_columns_for_table(name, table, use_rowid) # Allow for custom sort order sort = special_args.get("_sort") diff --git a/docs/metadata.rst b/docs/metadata.rst index 7ae561af..a0b1e88f 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -121,6 +121,23 @@ This will restrict sorting of ``example_table`` to just the ``height`` and You can also disable sorting entirely by setting ``"sortable_columns": []`` +By default, database views in Datasette do not support sorting. You can use ``sortable_columns`` to enable specific sort orders for a view called ``name_of_view`` in the database ``my_database`` like so:: + +{ + "databases": { + "my_database": { + "tables": { + "name_of_view": { + "sortable_columns": [ + "clicks", + "impressions" + ] + } + } + } + } +} + .. _label_columns: Specifying the label column for a table diff --git a/tests/fixtures.py b/tests/fixtures.py index ffacfa51..8f4b50dd 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -158,6 +158,9 @@ METADATA = { 'primary_key_multiple_columns_explicit_label': { 'label_column': 'content2', }, + 'simple_view': { + 'sortable_columns': ['content'], + } }, 'queries': { 'pragma_cache_size': 'PRAGMA cache_size;', diff --git a/tests/test_html.py b/tests/test_html.py index 5f59f61a..c3cf78b6 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -40,11 +40,6 @@ def test_sql_time_limit(app_client_shorter_time_limit): assert expected_html_fragment in response.text -def test_view(app_client): - response = app_client.get('/fixtures/simple_view') - assert response.status == 200 - - def test_row(app_client): response = app_client.get( '/fixtures/simple_primary_key/1', @@ -618,25 +613,33 @@ def test_compound_primary_key_with_foreign_key_references(app_client): def test_view_html(app_client): - response = app_client.get('/fixtures/simple_view') + response = app_client.get("/fixtures/simple_view") assert response.status == 200 - table = Soup(response.body, 'html.parser').find('table') - assert [ - 'content', 'upper_content' - ] == [th.string.strip() for th in table.select('thead th')] + table = Soup(response.body, "html.parser").find("table") + ths = table.select("thead th") + assert 2 == len(ths) + assert ths[0].find("a") is not None + assert ths[0].find("a")["href"].endswith("/simple_view?_sort=content") + assert ths[0].find("a").string.strip() == "content" + assert ths[1].find("a") is None + assert ths[1].string.strip() == "upper_content" expected = [ [ 'hello', - 'HELLO' - ], [ + 'HELLO', + ], + [ 'world', - 'WORLD' - ], [ + 'WORLD', + ], + [ '\xa0', - '\xa0' - ] + '\xa0', + ], + ] + assert expected == [ + [str(td) for td in tr.select("td")] for tr in table.select("tbody tr") ] - assert expected == [[str(td) for td in tr.select('td')] for tr in table.select('tbody tr')] def test_index_metadata(app_client):