From 50e1957c4ec6fda6cf7b6f7335f9dbf91d89b753 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sun, 15 Mar 2020 12:24:01 -0700 Subject: [PATCH] Initial work on add_column, refs #4 Still needs form validation and nice errors. --- datasette_edit_tables/app.py | 24 ++++++++++++-- .../templates/edit_tables_table.html | 17 ++++++++++ tests/test_edit_tables.py | 33 +++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/datasette_edit_tables/app.py b/datasette_edit_tables/app.py index e9f4221..9e4032b 100644 --- a/datasette_edit_tables/app.py +++ b/datasette_edit_tables/app.py @@ -124,20 +124,37 @@ def get_columns(conn): ) async def delete_table(self, database, table): - def delete_table(conn): + def do_delete_table(conn): db = sqlite_utils.Database(conn) db[table].disable_fts() db[table].drop() db.vacuum() await datasette.databases[database.name].execute_write_fn( - delete_table, block=True + do_delete_table, block=True ) return RedirectResponse( "/{}".format(quote_plus(database.name)), status_code=302, ) + async def add_column(self, database, table, formdata): + name = formdata["name"] + type = formdata["type"] + + def do_add_column(conn): + db = sqlite_utils.Database(conn) + db[table].add_column(name, type) + + await datasette.databases[database.name].execute_write_fn( + do_add_column, block=True + ) + + return RedirectResponse( + "/{}/{}".format(quote_plus(database.name), quote_plus(table)), + status_code=302, + ) + async def post(self, request): table = request.path_params["table"] databases = self.get_databases() @@ -154,6 +171,9 @@ async def post(self, request): if "delete_table" in formdata: return await self.delete_table(database, table) + if "add_column" in formdata: + return await self.add_column(database, table, formdata) + return HTMLResponse("Unknown operation", status_code=400) return EditTablesIndex, EditTablesDatabase, EditTablesTable diff --git a/datasette_edit_tables/templates/edit_tables_table.html b/datasette_edit_tables/templates/edit_tables_table.html index 7482865..f78e891 100644 --- a/datasette_edit_tables/templates/edit_tables_table.html +++ b/datasette_edit_tables/templates/edit_tables_table.html @@ -23,6 +23,23 @@

Columns

{% endfor %} +

Add a column

+ +
+ + +

+

+ +
+ +

Delete table

+
diff --git a/tests/test_edit_tables.py b/tests/test_edit_tables.py index 06af934..34b8e3c 100644 --- a/tests/test_edit_tables.py +++ b/tests/test_edit_tables.py @@ -65,3 +65,36 @@ async def test_delete_table(db_path): ) assert 302 == response.status_code assert "creatures" not in db.table_names() + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "col_type,expected_type", + [("text", str), ("integer", int), ("float", float), ("blob", bytes)], +) +async def test_add_column(db_path, col_type, expected_type): + app = Datasette([db_path]).app() + db = sqlite_utils.Database(db_path) + table = db["creatures"] + assert {"name": str, "description": str} == table.columns_dict + async with httpx.AsyncClient(app=app) as client: + # Get a csrftoken + csrftoken = ( + await client.get("http://localhost/-/edit-tables/data/creatures") + ).cookies["csrftoken"] + response = await client.post( + "http://localhost/-/edit-tables/data/creatures", + data={ + "add_column": "1", + "csrftoken": csrftoken, + "name": "new_col", + "type": col_type, + }, + allow_redirects=False, + ) + assert 302 == response.status_code + assert { + "name": str, + "description": str, + "new_col": expected_type, + } == table.columns_dict