Skip to content

Commit

Permalink
label_column option in metadata.json - closes #234
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Apr 22, 2018
1 parent ea0a761 commit f27cabb
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 3 deletions.
7 changes: 6 additions & 1 deletion datasette/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,12 @@ async def display_columns_and_rows(self, database, table, description, rows, lin
if table_info and expand_foreign_keys:
foreign_keys = table_info['foreign_keys']['outgoing']
for fk in foreign_keys:
label_column = tables.get(fk['other_table'], {}).get('label_column')
label_column = (
# First look for metadata.json definition:
table_metadata.get('label_column')
# Fall back to label_column from .inspect() detection:
or tables.get(fk['other_table'], {}).get('label_column')
)
if not label_column:
# No label for this FK
fks[fk['column']] = fk['other_table']
Expand Down
25 changes: 24 additions & 1 deletion docs/metadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Column units are configured in the metadata like so::
Units are interpreted using Pint_, and you can see the full list of available units in
Pint's `unit registry`_. You can also add `custom units`_ to the metadata, which will be
registered with Pint::

{
"custom_units": [
"decibel = [] = dB"
Expand Down Expand Up @@ -119,6 +119,29 @@ This will restrict sorting of ``example_table`` to just the ``height`` and

You can also disable sorting entirely by setting ``"sortable_columns": []``

Specifying the label column for a table
---------------------------------------

Datasette's HTML interface attempts to display foreign key references as
labelled hyperlinks. By default, it looks for referenced tables that only have
two columns: a primary key column and one other. It assumes that the second
column should be used as the link label.

If your table has more than two columns you can specify which column should be
used for the link label with the ``label_column`` property::

{
"databases": {
"database1": {
"tables": {
"example_table": {
"label_column": "title"
}
}
}
}
}

Generating a metadata skeleton
------------------------------

Expand Down
10 changes: 10 additions & 0 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ def generate_sortable_rows(num):
'frequency': 'Hz'
}
},
'custom_foreign_key_label': {
'label_column': 'content2',
},
}
},
}
Expand Down Expand Up @@ -215,6 +218,12 @@ def extra_js_urls():
FOREIGN KEY ("f3") REFERENCES [simple_primary_key](id)
);
CREATE TABLE "custom_foreign_key_label" (
pk varchar(30) primary key,
foreign_key_with_custom_label text,
FOREIGN KEY ("foreign_key_with_custom_label") REFERENCES [primary_key_multiple_columns](id)
);
CREATE TABLE units (
pk integer primary key,
distance int,
Expand All @@ -241,6 +250,7 @@ def extra_js_urls():
INSERT INTO foreign_key_references VALUES (1, 1, 1);
INSERT INTO complex_foreign_keys VALUES (1, 1, 2, 1);
INSERT INTO custom_foreign_key_label VALUES (1, 1);
INSERT INTO [table/with/slashes.csv] VALUES (3, 'hey');
Expand Down
21 changes: 20 additions & 1 deletion tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def test_homepage(app_client):
assert response.json.keys() == {'test_tables': 0}.keys()
d = response.json['test_tables']
assert d['name'] == 'test_tables'
assert d['tables_count'] == 13
assert d['tables_count'] == 14


def test_database_page(app_client):
Expand Down Expand Up @@ -80,6 +80,21 @@ def test_database_page(app_client):
'label_column': None,
'primary_keys': ['pk1', 'pk2', 'pk3'],
}, {
'columns': ['pk', 'foreign_key_with_custom_label'],
'name': 'custom_foreign_key_label',
'count': 1,
'hidden': False,
'foreign_keys': {
'incoming': [],
'outgoing': [{
'column': 'foreign_key_with_custom_label',
'other_column': 'id',
'other_table': 'primary_key_multiple_columns'
}],
},
'label_column': None,
'primary_keys': ['pk'],
}, {
'columns': ['pk', 'foreign_key_with_label', 'foreign_key_with_no_label'],
'name': 'foreign_key_references',
'count': 1,
Expand Down Expand Up @@ -115,6 +130,10 @@ def test_database_page(app_client):
'column': 'id',
'other_column': 'foreign_key_with_no_label',
'other_table': 'foreign_key_references'
}, {
'column': 'id',
'other_column': 'foreign_key_with_custom_label',
'other_table': 'custom_foreign_key_label'
}],
'outgoing': []
},
Expand Down
13 changes: 13 additions & 0 deletions tests/test_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,19 @@ def test_table_html_foreign_key_links(app_client):
assert expected == [[str(td) for td in tr.select('td')] for tr in table.select('tbody tr')]


def test_table_html_foreign_key_custom_label_column(app_client):
response = app_client.get('/test_tables/custom_foreign_key_label', gather_request=False)
assert response.status == 200
table = Soup(response.body, 'html.parser').find('table')
expected = [
[
'<td class="col-pk"><a href="/test_tables/custom_foreign_key_label/1">1</a></td>',
'<td class="col-foreign_key_with_custom_label"><a href="/test_tables/primary_key_multiple_columns/1">world</a>\xa0<em>1</em></td>',
]
]
assert expected == [[str(td) for td in tr.select('td')] for tr in table.select('tbody tr')]


def test_row_html_compound_primary_key(app_client):
response = app_client.get('/test_tables/compound_primary_key/a,b', gather_request=False)
assert response.status == 200
Expand Down

0 comments on commit f27cabb

Please sign in to comment.