From 2eb94ecba938b128fd26fad8297ff533bb5238b0 Mon Sep 17 00:00:00 2001 From: tmcl-it <82332573+tmcl-it@users.noreply.github.com> Date: Wed, 1 Mar 2023 18:39:35 +0100 Subject: [PATCH] Expand labels in row view as well --- datasette/views/row.py | 7 ++- datasette/views/table.py | 124 +++++++++++++++++++++------------------ tests/test_table_html.py | 31 ++++++++++ 3 files changed, 104 insertions(+), 58 deletions(-) diff --git a/datasette/views/row.py b/datasette/views/row.py index 4d317470e9..7785b55dea 100644 --- a/datasette/views/row.py +++ b/datasette/views/row.py @@ -7,7 +7,7 @@ to_css_class, escape_sqlite, ) -from .table import _sql_params_pks, display_columns_and_rows +from .table import _sql_params_pks, display_columns_and_rows, expand_labels class RowView(DataView): @@ -47,6 +47,11 @@ async def data(self, request, default_labels=False): if not rows: raise NotFound(f"Record not found") + # Expand labeled columns if requested + rows, _, _ = await expand_labels( + self.ds, db, request, table, columns, rows, default_labels + ) + async def template_data(): display_columns, display_rows = await display_columns_and_rows( self.ds, diff --git a/datasette/views/table.py b/datasette/views/table.py index 17d1b2485d..beec19b1f1 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -82,15 +82,6 @@ async def sortable_columns_for_table(self, database_name, table_name, use_rowid) sortable_columns.add("rowid") return sortable_columns - async def expandable_columns(self, database_name, table_name): - # Returns list of (fk_dict, label_column-or-None) pairs for that table - expandables = [] - db = self.ds.databases[database_name] - for fk in await db.foreign_keys_for_table(table_name): - label_column = await db.label_column_for_table(fk["other_table"]) - expandables.append((fk, label_column)) - return expandables - async def post(self, request): database_route = tilde_decode(request.url_vars["database"]) try: @@ -570,54 +561,15 @@ async def execute_suggested_facets(): rows = list(results.rows) # Expand labeled columns if requested - expanded_columns = [] - expandable_columns = await self.expandable_columns(database_name, table_name) - columns_to_expand = None - try: - all_labels = value_as_boolean(request.args.get("_labels", "")) - except ValueError: - all_labels = default_labels - # Check for explicit _label= - if "_label" in request.args: - columns_to_expand = request.args.getlist("_label") - if columns_to_expand is None and all_labels: - # expand all columns with foreign keys - columns_to_expand = [fk["column"] for fk, _ in expandable_columns] - - if columns_to_expand: - expanded_labels = {} - for fk, _ in expandable_columns: - column = fk["column"] - if column not in columns_to_expand: - continue - if column not in columns: - continue - expanded_columns.append(column) - # Gather the values - column_index = columns.index(column) - values = [row[column_index] for row in rows] - # Expand them - expanded_labels.update( - await self.ds.expand_foreign_keys( - database_name, table_name, column, values - ) - ) - if expanded_labels: - # Rewrite the rows - new_rows = [] - for row in rows: - new_row = CustomRow(columns) - for column in row.keys(): - value = row[column] - if (column, value) in expanded_labels and value is not None: - new_row[column] = { - "value": value, - "label": expanded_labels[(column, value)], - } - else: - new_row[column] = value - new_rows.append(new_row) - rows = new_rows + rows, expanded_columns, expandable_columns = await expand_labels( + self.ds, + db, + request, + table_name, + columns, + rows, + default_labels, + ) # Pagination next link next_value = None @@ -1023,3 +975,61 @@ async def display_columns_and_rows( } columns = [first_column] + columns return columns, cell_rows + + +async def expand_labels( + datasette, db, request, table_name, columns, rows, default_labels +): + """Expands labeled columns if requested""" + expanded_columns = [] + # List of (fk_dict, label_column-or-None) pairs for that table + expandable_columns = [] + for fk in await db.foreign_keys_for_table(table_name): + label_column = await db.label_column_for_table(fk["other_table"]) + expandable_columns.append((fk, label_column)) + columns_to_expand = None + try: + all_labels = value_as_boolean(request.args.get("_labels", "")) + except ValueError: + all_labels = default_labels + # Check for explicit _label= + if "_label" in request.args: + columns_to_expand = request.args.getlist("_label") + if columns_to_expand is None and all_labels: + # expand all columns with foreign keys + columns_to_expand = [fk["column"] for fk, _ in expandable_columns] + + if columns_to_expand: + expanded_labels = {} + for fk, _ in expandable_columns: + column = fk["column"] + if column not in columns_to_expand: + continue + if column not in columns: + continue + expanded_columns.append(column) + # Gather the values + column_index = columns.index(column) + values = [row[column_index] for row in rows] + # Expand them + expanded_labels.update( + await datasette.expand_foreign_keys(db.name, table_name, column, values) + ) + if expanded_labels: + # Rewrite the rows + new_rows = [] + for row in rows: + new_row = CustomRow(columns) + for column in row.keys(): + value = row[column] + if (column, value) in expanded_labels and value is not None: + new_row[column] = { + "value": value, + "label": expanded_labels[(column, value)], + } + else: + new_row[column] = value + new_rows.append(new_row) + rows = new_rows + + return rows, expanded_columns, expandable_columns diff --git a/tests/test_table_html.py b/tests/test_table_html.py index ae911d8e28..2a313a7f16 100644 --- a/tests/test_table_html.py +++ b/tests/test_table_html.py @@ -613,6 +613,37 @@ def test_table_html_foreign_key_links(app_client): ] +def test_row_html_foreign_key_links(app_client): + response = app_client.get("/fixtures/foreign_key_references/1") + assert response.status == 200 + table = Soup(response.body, "html.parser").find("table") + actual = [[str(td) for td in tr.select("td")] for tr in table.select("tbody tr")] + assert actual == [ + [ + '1', + 'hello\xa01', + '-\xa03', + '1', + 'a', + 'b', + ], + ] + response = app_client.get("/fixtures/foreign_key_references/2") + assert response.status == 200 + table = Soup(response.body, "html.parser").find("table") + actual = [[str(td) for td in tr.select("td")] for tr in table.select("tbody tr")] + assert actual == [ + [ + '2', + '\xa0', + '\xa0', + '\xa0', + '\xa0', + '\xa0', + ], + ] + + def test_table_html_foreign_key_facets(app_client): response = app_client.get( "/fixtures/foreign_key_references?_facet=foreign_key_with_blank_label"