From d2405a66ac55423513bc9a71abcf6297fd4bf00a Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 3 Sep 2024 14:27:51 -0700 Subject: [PATCH] Improved row editing with custom title Also support for ?id_hidden=x parameters --- datasette_write/__init__.py | 54 ++++++++++++++----- .../templates/datasette_write.html | 13 ++++- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/datasette_write/__init__.py b/datasette_write/__init__.py index 011cd86..5d336a4 100644 --- a/datasette_write/__init__.py +++ b/datasette_write/__init__.py @@ -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, @@ -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: @@ -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 ] @@ -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), diff --git a/datasette_write/templates/datasette_write.html b/datasette_write/templates/datasette_write.html index d51af03..c06d868 100644 --- a/datasette_write/templates/datasette_write.html +++ b/datasette_write/templates/datasette_write.html @@ -41,17 +41,21 @@ {% endblock %} {% block content %} -

Write to {{ database_name }} with SQL

+

{% if custom_title %}{{ custom_title }}{% else %}Write to {{ database_name }} with SQL{% endif %}

-

+ {% if custom_title %}
SQL query{% endif %} +

+ {% if custom_title %}
{% endif %}
{% for parameter in parameters %} {% if parameter.type == "text" %} + {% elif parameter.type == "hidden" %} + {% elif parameter.type == "textarea" %} {% endif %} @@ -96,6 +100,11 @@

Write to {{ database_name }} with SQL

`; + } else if (param.type === 'hidden') { + htmlString += ` + + + `; } }); return htmlString;