Fixed incorrect display of compound primary keys with foreign key references

Closes #319
pull/322/head^2
Simon Willison 2018-06-21 07:56:28 -07:00
rodzic 3683a6b626
commit 3b53eea382
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 17E2DEA2588B7F52
5 zmienionych plików z 122 dodań i 10 usunięć

Wyświetl plik

@ -70,8 +70,10 @@ def path_from_row_pks(row, pks, use_rowid, quote=True):
if use_rowid:
bits = [row['rowid']]
else:
bits = [row[pk] for pk in pks]
bits = [
row[pk]["value"] if isinstance(row[pk], dict) else row[pk]
for pk in pks
]
if quote:
bits = [urllib.parse.quote_plus(str(bit)) for bit in bits]
else:
@ -817,8 +819,10 @@ def path_with_format(request, format, extra_qs=None):
class CustomRow(OrderedDict):
# Loose imitation of sqlite3.Row which offers
# both index-based AND key-based lookups
def __init__(self, columns):
def __init__(self, columns, values=None):
self.columns = columns
if values:
self.update(values)
def __getitem__(self, key):
if isinstance(key, int):

Wyświetl plik

@ -303,6 +303,10 @@ INSERT INTO units VALUES (1, 1, 100);
INSERT INTO units VALUES (2, 5000, 2500);
INSERT INTO units VALUES (3, 100000, 75000);
CREATE TABLE tags (
tag TEXT PRIMARY KEY
);
CREATE TABLE searchable (
pk integer primary key,
text1 text,
@ -310,9 +314,25 @@ CREATE TABLE searchable (
[name with . and spaces] text
);
CREATE TABLE searchable_tags (
searchable_id integer,
tag text,
PRIMARY KEY (searchable_id, tag),
FOREIGN KEY (searchable_id) REFERENCES searchable(pk),
FOREIGN KEY (tag) REFERENCES tags(tag)
);
INSERT INTO searchable VALUES (1, 'barry cat', 'terry dog', 'panther');
INSERT INTO searchable VALUES (2, 'terry dog', 'sara weasel', 'puma');
INSERT INTO tags VALUES ("canine");
INSERT INTO tags VALUES ("feline");
INSERT INTO searchable_tags (searchable_id, tag) VALUES
(1, "feline"),
(2, "canine")
;
CREATE VIRTUAL TABLE "searchable_fts"
USING FTS3 (text1, text2, [name with . and spaces], content="searchable");
INSERT INTO "searchable_fts" (rowid, text1, text2, [name with . and spaces])

Wyświetl plik

@ -17,7 +17,7 @@ def test_homepage(app_client):
assert response.json.keys() == {'fixtures': 0}.keys()
d = response.json['fixtures']
assert d['name'] == 'fixtures'
assert d['tables_count'] == 17
assert d['tables_count'] == 19
def test_database_page(app_client):
@ -188,11 +188,38 @@ def test_database_page(app_client):
'columns': ['pk', 'text1', 'text2', 'name with . and spaces'],
'name': 'searchable',
'count': 2,
'foreign_keys': {'incoming': [], 'outgoing': []},
'foreign_keys': {'incoming': [{
"other_table": "searchable_tags",
"column": "pk",
"other_column": "searchable_id"
}], 'outgoing': []},
'fts_table': 'searchable_fts',
'hidden': False,
'label_column': None,
'primary_keys': ['pk'],
}, {
"name": "searchable_tags",
"columns": ["searchable_id", "tag"],
"primary_keys": ["searchable_id", "tag"],
"count": 2,
"label_column": None,
"hidden": False,
"fts_table": None,
"foreign_keys": {
"incoming": [],
"outgoing": [
{
"other_table": "tags",
"column": "tag",
"other_column": "tag",
},
{
"other_table": "searchable",
"column": "searchable_id",
"other_column": "pk",
},
],
},
}, {
'columns': ['group', 'having', 'and'],
'name': 'select',
@ -251,6 +278,24 @@ def test_database_page(app_client):
'label_column': None,
'fts_table': None,
'primary_keys': ['pk'],
}, {
"name": "tags",
"columns": ["tag"],
"primary_keys": ["tag"],
"count": 2,
"label_column": None,
"hidden": False,
"fts_table": None,
"foreign_keys": {
"incoming": [
{
"other_table": "searchable_tags",
"column": "tag",
"other_column": "tag",
}
],
"outgoing": [],
},
}, {
'columns': ['pk', 'distance', 'frequency'],
'name': 'units',

Wyświetl plik

@ -550,6 +550,26 @@ def test_row_html_compound_primary_key(app_client):
assert expected == [[str(td) for td in tr.select('td')] for tr in table.select('tbody tr')]
def test_compound_primary_key_with_foreign_key_references(app_client):
# e.g. a many-to-many table with a compound primary key on the two columns
response = app_client.get('/fixtures/searchable_tags')
assert response.status == 200
table = Soup(response.body, 'html.parser').find('table')
expected = [
[
'<td class="col-Link"><a href="/fixtures/searchable_tags/1,feline">1,feline</a></td>',
'<td class="col-searchable_id"><a href="/fixtures/searchable/1">1</a>\xa0<em>1</em></td>',
'<td class="col-tag"><a href="/fixtures/tags/feline">feline</a></td>',
],
[
'<td class="col-Link"><a href="/fixtures/searchable_tags/2,canine">2,canine</a></td>',
'<td class="col-searchable_id"><a href="/fixtures/searchable/2">2</a>\xa0<em>2</em></td>',
'<td class="col-tag"><a href="/fixtures/tags/canine">canine</a></td>',
],
]
assert expected == [[str(td) for td in tr.select('td')] for tr in table.select('tbody tr')]
def test_view_html(app_client):
response = app_client.get('/fixtures/simple_view')
assert response.status == 200

Wyświetl plik

@ -75,11 +75,34 @@ def test_path_with_replaced_args(path, args, expected):
assert expected == actual
@pytest.mark.parametrize('row,pks,expected_path', [
({'A': 'foo', 'B': 'bar'}, ['A', 'B'], 'foo,bar'),
({'A': 'f,o', 'B': 'bar'}, ['A', 'B'], 'f%2Co,bar'),
({'A': 123}, ['A'], '123'),
])
@pytest.mark.parametrize(
"row,pks,expected_path",
[
({"A": "foo", "B": "bar"}, ["A", "B"], "foo,bar"),
({"A": "f,o", "B": "bar"}, ["A", "B"], "f%2Co,bar"),
({"A": 123}, ["A"], "123"),
(
utils.CustomRow(
["searchable_id", "tag"],
[
(
"searchable_id",
{"value": 1, "label": "1"},
),
(
"tag",
{
"value": "feline",
"label": "feline",
},
),
],
),
["searchable_id", "tag"],
"1,feline",
),
],
)
def test_path_from_row_pks(row, pks, expected_path):
actual_path = utils.path_from_row_pks(row, pks, False)
assert expected_path == actual_path