html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,issue,performed_via_github_app
https://github.com/simonw/datasette/issues/1195#issuecomment-763108730,https://api.github.com/repos/simonw/datasette/issues/1195,763108730,MDEyOklzc3VlQ29tbWVudDc2MzEwODczMA==,9599,2021-01-19T20:22:37Z,2021-01-19T20:22:37Z,OWNER,I can use this test: https://github.com/simonw/datasette/blob/c38c42948cbfddd587729413fd6082ba352eaece/tests/test_plugins.py#L238-L294,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",789336592,
https://github.com/simonw/datasette/issues/1195#issuecomment-766534634,https://api.github.com/repos/simonw/datasette/issues/1195,766534634,MDEyOklzc3VlQ29tbWVudDc2NjUzNDYzNA==,9599,2021-01-25T04:38:30Z,2021-01-25T04:38:30Z,OWNER,"This has proved surprisingly difficult to implement, due to the weird way the QueryView is actually called. The class itself isn't used like other view classes - instead, the `.data()` methods of both `DatabaseView` and `TableView` dispatch out to `QueryView.data()` when they need to:
https://github.com/simonw/datasette/blob/07e163561592c743e4117f72102fcd350a600909/datasette/views/table.py#L259-L270
https://github.com/simonw/datasette/blob/07e163561592c743e4117f72102fcd350a600909/datasette/views/table.py#L290-L294
https://github.com/simonw/datasette/blob/07e163561592c743e4117f72102fcd350a600909/datasette/views/database.py#L39-L44
It turns out this is a bad pattern because it makes changes like this one WAY harder than they should be.
I think I should clean this up as part of #878.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",789336592,
https://github.com/simonw/datasette/issues/1195#issuecomment-766534748,https://api.github.com/repos/simonw/datasette/issues/1195,766534748,MDEyOklzc3VlQ29tbWVudDc2NjUzNDc0OA==,9599,2021-01-25T04:38:56Z,2021-01-25T04:38:56Z,OWNER,"Here's a diff showing how far I got before I abandoned this particular effort:
```diff
diff --git a/datasette/views/base.py b/datasette/views/base.py
index a21b929..04e4aa9 100644
--- a/datasette/views/base.py
+++ b/datasette/views/base.py
@@ -120,7 +120,7 @@ class BaseView:
handler = getattr(self, request.method.lower(), None)
return await handler(request, *args, **kwargs)
- async def render(self, templates, request, context=None):
+ async def render(self, templates, request, context=None, view_name=None):
context = context or {}
template = self.ds.jinja_env.select_template(templates)
template_context = {
@@ -135,7 +135,7 @@ class BaseView:
}
return Response.html(
await self.ds.render_template(
- template, template_context, request=request, view_name=self.name
+ template, template_context, request=request, view_name=view_name
)
)
@@ -155,7 +155,7 @@ class BaseView:
class DataView(BaseView):
- name = """"
+ view_name = ""no-view-name""
re_named_parameter = re.compile("":([a-zA-Z0-9_]+)"")
async def options(self, request, *args, **kwargs):
@@ -414,6 +414,10 @@ class DataView(BaseView):
args[""table""] = urllib.parse.unquote_plus(args[""table""])
return _format, args
+ async def get_view_name(self, request, database, hash, **kwargs):
+ # Defaults to self.view_name, but can be over-ridden by subclasses
+ return self.view_name
+
async def view_get(self, request, database, hash, correct_hash_provided, **kwargs):
_format, kwargs = await self.get_format(request, database, kwargs)
@@ -424,6 +428,8 @@ class DataView(BaseView):
# HTML views default to expanding all foreign key labels
kwargs[""default_labels""] = True
+ view_name = await self.get_view_name(request, database, hash, **kwargs)
+
extra_template_data = {}
start = time.perf_counter()
status_code = 200
@@ -489,7 +495,7 @@ class DataView(BaseView):
database=database,
table=data.get(""table""),
request=request,
- view_name=self.name,
+ view_name=view_name,
# These will be deprecated in Datasette 1.0:
args=request.args,
data=data,
@@ -533,7 +539,7 @@ class DataView(BaseView):
database=database,
table=data.get(""table""),
request=request,
- view_name=self.name,
+ view_name=view_name,
)
it_can_render = await await_me_maybe(it_can_render)
if it_can_render:
@@ -565,7 +571,7 @@ class DataView(BaseView):
}
if ""metadata"" not in context:
context[""metadata""] = self.ds.metadata
- r = await self.render(templates, request=request, context=context)
+ r = await self.render(templates, request=request, context=context, view_name=view_name)
r.status = status_code
ttl = request.args.get(""_ttl"", None)
diff --git a/datasette/views/database.py b/datasette/views/database.py
index f6fd579..e425213 100644
--- a/datasette/views/database.py
+++ b/datasette/views/database.py
@@ -23,7 +23,11 @@ from .base import DatasetteError, DataView
class DatabaseView(DataView):
- name = ""database""
+ async def get_view_name(self, request, db_name, table_and_format):
+ if request.args.get(""sql""):
+ return ""query""
+ else:
+ return ""database""
async def data(self, request, database, hash, default_labels=False, _size=None):
await self.check_permissions(
@@ -145,7 +149,7 @@ class DatabaseView(DataView):
class DatabaseDownload(DataView):
- name = ""database_download""
+ view_name = ""database_download""
async def view_get(self, request, database, hash, correct_hash_present, **kwargs):
await self.check_permissions(
diff --git a/datasette/views/index.py b/datasette/views/index.py
index b6b8cbe..d750e3d 100644
--- a/datasette/views/index.py
+++ b/datasette/views/index.py
@@ -16,7 +16,7 @@ COUNT_DB_SIZE_LIMIT = 100 * 1024 * 1024
class IndexView(BaseView):
- name = ""index""
+ view_name = ""index""
async def get(self, request, as_format):
await self.check_permission(request, ""view-instance"")
diff --git a/datasette/views/special.py b/datasette/views/special.py
index 9750dd0..dbd1e00 100644
--- a/datasette/views/special.py
+++ b/datasette/views/special.py
@@ -6,7 +6,7 @@ import secrets
class JsonDataView(BaseView):
- name = ""json_data""
+ view_name = ""json_data""
def __init__(self, datasette, filename, data_callback, needs_request=False):
self.ds = datasette
@@ -42,7 +42,7 @@ class JsonDataView(BaseView):
class PatternPortfolioView(BaseView):
- name = ""patterns""
+ view_name = ""patterns""
async def get(self, request):
await self.check_permission(request, ""view-instance"")
@@ -50,7 +50,7 @@ class PatternPortfolioView(BaseView):
class AuthTokenView(BaseView):
- name = ""auth_token""
+ view_name = ""auth_token""
async def get(self, request):
token = request.args.get(""token"") or """"
@@ -68,7 +68,7 @@ class AuthTokenView(BaseView):
class LogoutView(BaseView):
- name = ""logout""
+ view_name = ""logout""
async def get(self, request):
if not request.actor:
@@ -87,7 +87,7 @@ class LogoutView(BaseView):
class PermissionsDebugView(BaseView):
- name = ""permissions_debug""
+ view_name = ""permissions_debug""
async def get(self, request):
await self.check_permission(request, ""view-instance"")
@@ -102,7 +102,7 @@ class PermissionsDebugView(BaseView):
class AllowDebugView(BaseView):
- name = ""allow_debug""
+ view_name = ""allow_debug""
async def get(self, request):
errors = []
@@ -136,7 +136,7 @@ class AllowDebugView(BaseView):
class MessagesDebugView(BaseView):
- name = ""messages_debug""
+ view_name = ""messages_debug""
async def get(self, request):
await self.check_permission(request, ""view-instance"")
diff --git a/datasette/views/table.py b/datasette/views/table.py
index 0a3504b..45d298a 100644
--- a/datasette/views/table.py
+++ b/datasette/views/table.py
@@ -257,7 +257,16 @@ class RowTableShared(DataView):
class TableView(RowTableShared):
- name = ""table""
+ view_name = ""table""
+
+ async def get_view_name(self, request, db_name, table_and_format):
+ canned_query = await self.ds.get_canned_query(
+ db_name, table_and_format, request.actor
+ )
+ if canned_query:
+ return ""query""
+ else:
+ return ""table""
async def post(self, request, db_name, table_and_format):
# Handle POST to a canned query
@@ -923,7 +932,7 @@ async def _sql_params_pks(db, table, pk_values):
class RowView(RowTableShared):
- name = ""row""
+ view_name = ""row""
async def data(self, request, database, hash, table, pk_path, default_labels=False):
await self.check_permissions(
diff --git a/tests/test_plugins.py b/tests/test_plugins.py
index 715c7c1..7ce2b1b 100644
--- a/tests/test_plugins.py
+++ b/tests/test_plugins.py
@@ -252,7 +252,7 @@ def test_plugin_config_file(app_client):
},
),
(
- ""/fixtures/"",
+ ""/fixtures"",
{
""template"": ""database.html"",
""database"": ""fixtures"",
@@ -285,6 +285,38 @@ def test_plugin_config_file(app_client):
],
},
),
+ (
+ ""/fixtures?sql=select+1+as+one"",
+ {
+ ""template"": ""query.html"",
+ ""database"": ""fixtures"",
+ ""table"": None,
+ ""config"": {""depth"": ""database""},
+ ""view_name"": ""query"",
+ ""request_path"": ""/fixtures"",
+ ""added"": 15,
+ ""columns"": [
+ ""one"",
+ ],
+ },
+ ),
+ (
+ ""/fixtures/neighborhood_search"",
+ {
+ ""template"": ""query.html"",
+ ""database"": ""fixtures"",
+ ""table"": None,
+ ""config"": {""depth"": ""database""},
+ ""view_name"": ""query"",
+ ""request_path"": ""/fixtures/neighborhood_search"",
+ ""added"": 15,
+ ""columns"": [
+ ""neighborhood"",
+ ""name"",
+ ""state"",
+ ],
+ },
+ ),
],
)
def test_hook_extra_body_script(app_client, path, expected_extra_body_script):
```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",789336592,
https://github.com/simonw/datasette/issues/1195#issuecomment-766535046,https://api.github.com/repos/simonw/datasette/issues/1195,766535046,MDEyOklzc3VlQ29tbWVudDc2NjUzNTA0Ng==,9599,2021-01-25T04:40:08Z,2021-01-25T04:40:08Z,OWNER,"Also: should the view name really be the same for both of these pages?
- https://latest.datasette.io/fixtures?sql=select+*+from+facetable
- https://latest.datasette.io/fixtures/neighborhood_search
Where one of them is a canned query and the other is an arbitrary query?","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",789336592,