Skip to content

Commit

Permalink
Improved row editing with custom title
Browse files Browse the repository at this point in the history
Also support for ?id_hidden=x parameters
  • Loading branch information
simonw committed Sep 3, 2024
1 parent 2a20e23 commit d2405a6
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 16 deletions.
54 changes: 40 additions & 14 deletions datasette_write/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,18 @@ async def write(request, datasette):
# Set values based on incoming request query string
for parameter in parameters:
parameter["value"] = request.args.get(parameter["name"]) or ""
custom_title = ""
try:
custom_title = datasette.unsign(
request.args.get("_title", ""), "query_title"
)
except itsdangerous.BadSignature:
pass
return Response.html(
await datasette.render_template(
"datasette_write.html",
{
"custom_title": custom_title,
"sql_from_args": sql,
"parameters": parameters,
"database_name": database_name,
Expand Down Expand Up @@ -83,7 +91,7 @@ async def write(request, datasette):
try:
# Unless value and valid signature for _redirect_to=
redirect_to = datasette.unsign(formdata["_redirect_to"], "redirect_to")
except (KeyError, ValueError):
except itsdangerous.BadSignature:
pass
return Response.redirect(redirect_to)
else:
Expand Down Expand Up @@ -113,16 +121,24 @@ async def write_redirect(request, datasette):

async def derive_parameters(db, sql):
parameters = await derive_named_parameters(db, sql)

def _type(parameter):
type = "text"
if parameter.endswith("_textarea"):
type = "textarea"
if parameter.endswith("_hidden"):
type = "hidden"
return type

def _label(parameter):
if parameter.endswith("_textarea"):
return parameter[: -len("_textarea")]
if parameter.endswith("_hidden"):
return parameter[: -len("_hidden")]
return parameter

return [
{
"name": parameter,
"type": "textarea" if parameter.endswith("textarea") else "text",
"label": (
parameter.replace("_textarea", "")
if parameter.endswith("textarea")
else parameter
),
}
{"name": parameter, "type": _type(parameter), "label": _label(parameter)}
for parameter in parameters
]

Expand Down Expand Up @@ -202,21 +218,31 @@ async def inner():
if "\n" in current_value:
field_name = field_name + "_textarea"
if column["notnull"]:
fragment = "{} = :{}"
fragment = '"{}" = :{}'
else:
fragment = "{} = nullif(:{}, '')"
fragment = "\"{}\" = nullif(:{}, '')"
set_clause_bits.append(fragment.format(column["name"], field_name))
args[field_name] = current_value
set_clauses = ",\n ".join(set_clause_bits)

where_clauses = " and ".join("{} = :{}".format(pk, pk) for pk in pks)
args.update([(pk, row_dict[pk]) for pk in pks])
# Add the where clauses, with _hidden to prevent edits
where_clauses = " and ".join(
'"{}" = :{}_hidden'.format(pk, pk) for pk in pks
)
args.update([("{}_hidden".format(pk), row_dict[pk]) for pk in pks])

row_desc = ", ".join(
"{}={}".format(k, v) for k, v in row_dict.items() if k in pks
)

sql = 'update "{}" set\n {}\nwhere {}'.format(
table, set_clauses, where_clauses
)
args["sql"] = sql
args["_redirect_to"] = datasette.sign(request.path, "redirect_to")
args["_title"] = datasette.sign(
"Update {} where {}".format(table, row_desc), "query_title"
)
return [
{
"href": datasette.urls.path("/-/write") + "?" + urlencode(args),
Expand Down
13 changes: 11 additions & 2 deletions datasette_write/templates/datasette_write.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,21 @@
{% endblock %}

{% block content %}
<h1>Write to {{ database_name }} with SQL</h1>
<h1>{% if custom_title %}{{ custom_title }}{% else %}Write to {{ database_name }} with SQL{% endif %}</h1>

<form class="write-form core" action="{{ request.path }}" method="post" style="margin-bottom: 1em">
<input type="hidden" name="csrftoken" value="{{ csrftoken() }}">
<p><textarea name="sql" style="box-sizing: border-box; width: 100%; padding-right: 10px; max-width: 600px; height: {{ sql_textarea_height }}em; padding: 6px;">{{ sql_from_args }}</textarea></p>
{% if custom_title %}<details style="margin-bottom: 1em"><summary>SQL query</summary>{% endif %}
<p><textarea name="sql" style="box-sizing: border-box; width: 100%; padding-right: 10px; max-width: 600px; height: {{ sql_textarea_height }}em; padding: 6px;">{{ sql_from_args }}</textarea></p>
{% if custom_title %}</details>{% endif %}
<div class="query-parameters">
<div id="query-parameters-area">
{% for parameter in parameters %}
<label for="qp_{{ parameter.name }}">{{ parameter.label }}</label>
{% if parameter.type == "text" %}
<input type="text" id="qp_{{ parameter.name }}" name="qp_{{ parameter.name }}" value="{{ parameter.value }}">
{% elif parameter.type == "hidden" %}
<input type="text" disabled id="qp_{{ parameter.name }}" name="qp_{{ parameter.name }}" value="{{ parameter.value }}">
{% elif parameter.type == "textarea" %}
<textarea id="qp_{{ parameter.name }}" name="qp_{{ parameter.name }}">{{ parameter.value }}</textarea>
{% endif %}
Expand Down Expand Up @@ -96,6 +100,11 @@ <h1>Write to {{ database_name }} with SQL</h1>
<label for="qp_${param.name}">${param.label}</label>
<textarea id="qp_${param.name}" name="qp_${param.name}">${value}</textarea>
`;
} else if (param.type === 'hidden') {
htmlString += `
<span></span>
<input type="hidden" id="qp_${param.name}" name="qp_${param.name}" value="${value}">
`;
}
});
return htmlString;
Expand Down

0 comments on commit d2405a6

Please sign in to comment.