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 %} -