From b1e168b9c907d9b6c37fb3188fa2053baf56d5d1 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 1 Jul 2020 14:03:15 -0700 Subject: [PATCH] Incomplete WIP for #880 --- datasette/views/base.py | 8 +++++--- datasette/views/database.py | 11 +++++++++++ datasette/views/table.py | 16 +++++++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/datasette/views/base.py b/datasette/views/base.py index 399b1a1f..ed50edeb 100644 --- a/datasette/views/base.py +++ b/datasette/views/base.py @@ -356,12 +356,14 @@ class DataView(BaseView): if "table_and_format" in args: db = self.ds.databases[database] - async def async_table_exists(t): - return await db.table_exists(t) + async def async_table_or_query_exists(t): + return await db.table_exists(t) or await self.ds.get_canned_query( + database, t, request.actor + ) table, _ext_format = await resolve_table_and_format( table_and_format=urllib.parse.unquote_plus(args["table_and_format"]), - table_exists=async_table_exists, + table_exists=async_table_or_query_exists, allowed_formats=self.ds.renderers.keys(), ) _format = _format or _ext_format diff --git a/datasette/views/database.py b/datasette/views/database.py index 9d639170..b85ed757 100644 --- a/datasette/views/database.py +++ b/datasette/views/database.py @@ -144,6 +144,7 @@ class QueryView(DataView): _size=None, named_parameters=None, write=False, + json_format=False, ): params = {key: request.args.get(key) for key in request.args} if "sql" in params: @@ -212,6 +213,16 @@ class QueryView(DataView): message = metadata.get("on_error_message") or str(e) message_type = self.ds.ERROR redirect_url = metadata.get("on_error_redirect") + if json_format: + return ( + { + "message": message, + "message_type": message_type, + "redirect_url": redirect_url, + }, + {}, + [], + ) self.ds.add_message(request, message, message_type) return self.redirect(request, redirect_url or request.path) else: diff --git a/datasette/views/table.py b/datasette/views/table.py index e0a52e20..3f24a2f6 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -18,6 +18,7 @@ from datasette.utils import ( path_with_added_args, path_with_removed_args, path_with_replaced_args, + resolve_table_and_format, sqlite3, to_css_class, urlsafe_components, @@ -223,9 +224,17 @@ class TableView(RowTableShared): async def post(self, request, db_name, table_and_format): # Handle POST to a canned query - canned_query = await self.ds.get_canned_query( - db_name, table_and_format, request.actor + async def async_query_exists(query): + canned_query = await self.ds.get_canned_query(db_name, query, request.actor) + return bool(canned_query) + + query, _format = await resolve_table_and_format( + table_and_format=urllib.parse.unquote_plus(table_and_format), + table_exists=async_query_exists, + allowed_formats=self.ds.renderers.keys(), ) + + canned_query = await self.ds.get_canned_query(db_name, query, request.actor) assert canned_query, "You may only POST to a canned query" return await QueryView(self.ds).data( request, @@ -234,9 +243,10 @@ class TableView(RowTableShared): canned_query["sql"], metadata=canned_query, editable=False, - canned_query=table_and_format, + canned_query=query, named_parameters=canned_query.get("params"), write=bool(canned_query.get("write")), + json_format=(_format == "json"), ) async def data(