From 6a007f632258e6cfd3c5e9e229683deb0efd87be Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Fri, 17 Nov 2017 10:15:44 -0800 Subject: [PATCH] Row pages show incoming foreign key relationships --- datasette/app.py | 28 ++++++++++++++++++++++++++++ datasette/templates/row.html | 14 ++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/datasette/app.py b/datasette/app.py index 2a7a5e2b..c6ead0f9 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -590,8 +590,36 @@ class RowView(BaseView): 'primary_key_values': pk_values, }, { 'database_hash': hash, + 'foreign_key_tables': await self.foreign_key_tables(name, table, pk_values), } + async def foreign_key_tables(self, name, table, pk_values): + if len(pk_values) != 1: + return [] + table_info = self.ds.inspect()[name]['tables'].get(table) + if not table: + return [] + foreign_keys = table_info['foreign_keys']['incoming'] + sql = 'select ' + ', '.join([ + '(select count(*) from {table} where "{column}"= :id)'.format( + table=escape_sqlite_table_name(fk['other_table']), + column=fk['other_column'], + ) + for fk in foreign_keys + ]) + try: + rows = list(await self.execute(name, sql, {'id': pk_values[0]})) + except sqlite3.OperationalError: + # Almost certainly hit the timeout + return [] + foreign_table_counts = dict(zip([fk['other_table'] for fk in foreign_keys], rows[0])) + foreign_key_tables = [] + for fk in foreign_keys: + count = foreign_table_counts[fk['other_table']] + if count: + foreign_key_tables.append({**fk, **{'count': count}}) + return foreign_key_tables + class Datasette: def __init__( diff --git a/datasette/templates/row.html b/datasette/templates/row.html index 2d4ca39b..c4ecf959 100644 --- a/datasette/templates/row.html +++ b/datasette/templates/row.html @@ -35,4 +35,18 @@ {% endfor %} + +{% if foreign_key_tables %} +

Links from other tables

+ +{% endif %} + {% endblock %}