diff --git a/datasette/app.py b/datasette/app.py index ea632701..a3ef0752 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -2317,6 +2317,10 @@ ORDER BY allowed.parent, allowed.child from datasette.resources import TableResource other_table = fk["other_table"] + if not await db.table_exists(other_table): + # SQLite accepts a foreign key to a table that does not exist, and + # linking to it would only lead to a 404 + return {} other_column = fk["other_column"] if other_column is None: other_pks = await db.primary_keys(other_table) diff --git a/tests/test_table_html.py b/tests/test_table_html.py index c72aaf9b..7458921d 100644 --- a/tests/test_table_html.py +++ b/tests/test_table_html.py @@ -803,6 +803,38 @@ async def test_table_html_foreign_key_links(ds_client): ] +@pytest.mark.asyncio +async def test_table_html_foreign_key_to_missing_table_is_not_linked(): + # https://github.com/simonw/datasette/issues/1515 + ds = Datasette([]) + db = ds.add_database( + Database(ds, memory_name="test_foreign_key_to_missing_table"), name="data" + ) + await db.execute_write_script(""" + create table authors (id integer primary key, name text); + create table books ( + id integer primary key, + author_id integer references authors(id), + missing_id integer references missing_table(id) + ); + insert into authors (id, name) values (1, 'Ada'); + insert into books (id, author_id, missing_id) values (1, 1, 7); + """) + response = await ds.client.get("/data/books") + assert response.status_code == 200 + table = Soup(response.text, "html.parser").find("table") + cells = {td["class"][0]: str(td) for td in table.select("tbody tr")[0].select("td")} + assert cells["col-author_id"] == ( + '