Magic parameters for canned queries

Closes #842

Includes a new plugin hook, register_magic_parameters()
This commit is contained in:
Simon Willison 2020-06-27 19:58:16 -07:00 committed by GitHub
commit 563f5a2d3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 477 additions and 167 deletions

View file

@ -1,4 +1,5 @@
import os
import itertools
import jinja2
from datasette.utils import (
@ -165,11 +166,12 @@ class QueryView(DataView):
named_parameter_values = {
named_parameter: params.get(named_parameter) or ""
for named_parameter in named_parameters
if not named_parameter.startswith("_")
}
# Set to blank string if missing from params
for named_parameter in named_parameters:
if named_parameter not in params:
if named_parameter not in params and not named_parameter.startswith("_"):
params[named_parameter] = ""
extra_args = {}
@ -184,9 +186,13 @@ class QueryView(DataView):
if write:
if request.method == "POST":
params = await request.post_vars()
if canned_query:
params_for_query = MagicParameters(params, request, self.ds)
else:
params_for_query = params
try:
cursor = await self.ds.databases[database].execute_write(
sql, params, block=True
sql, params_for_query, block=True
)
message = metadata.get(
"on_success_message"
@ -227,8 +233,12 @@ class QueryView(DataView):
templates,
)
else: # Not a write
if canned_query:
params_for_query = MagicParameters(params, request, self.ds)
else:
params_for_query = params
results = await self.ds.execute(
database, sql, params, truncate=True, **extra_args
database, sql, params_for_query, truncate=True, **extra_args
)
columns = [r[0] for r in results.description]
@ -298,3 +308,25 @@ class QueryView(DataView):
extra_template,
templates,
)
class MagicParameters(dict):
def __init__(self, data, request, datasette):
super().__init__(data)
self._request = request
self._magics = dict(
itertools.chain.from_iterable(
pm.hook.register_magic_parameters(datasette=datasette)
)
)
def __getitem__(self, key):
if key.startswith("_") and key.count("_") >= 2:
prefix, suffix = key[1:].split("_", 1)
if prefix in self._magics:
try:
return self._magics[prefix](suffix, self._request)
except KeyError:
return super().__getitem__(key)
else:
return super().__getitem__(key)