datasette icon indicating copy to clipboard operation
datasette copied to clipboard

request.post_vars() method obliterates form keys with multiple values

Open simonw opened this issue 2 years ago • 3 comments

https://github.com/simonw/datasette/blob/452a587e236ef642cbc6ae345b58767ea8420cb5/datasette/utils/asgi.py#L137-L139

In GET requests you can do ?foo=1&foo=2 - you can do the same in POST requests, but the dict() call here eliminates those duplicates.

You can't even try calling post_body() and implement your own custom parsing because of:

  • #2204

simonw avatar Nov 05 '23 23:11 simonw

I found this problem while trying to use WTForms with this pattern:

choices = [(col, col) for col in await db.table_columns(table)]

class ConfigForm(Form):
    template = TextAreaField("Template")
    api_token = PasswordField("OpenAI API token")
    columns = MultiCheckboxField('Columns', choices=choices)

simonw avatar Nov 05 '23 23:11 simonw

It should return a MultiParams:

https://github.com/simonw/datasette/blob/452a587e236ef642cbc6ae345b58767ea8420cb5/datasette/utils/init.py#L900-L917

Change needs to be made before 1.0.

return MultiParams(urllib.parse.parse_qs(body.decode("utf-8")))

Need to remember why I was using keep_blank_values=True there and check that using MultiParams doesn't conflict with that reason.

simonw avatar Nov 06 '23 04:11 simonw

That keep_blank_values=True is from https://github.com/simonw/datasette/commit/0934844c0b6d124163d0185fb6a41ba5a71433da

Commit message:

request.post_vars() no longer discards empty values

Relevant test:

https://github.com/simonw/datasette/blob/452a587e236ef642cbc6ae345b58767ea8420cb5/tests/test_internals_request.py#L19-L27

simonw avatar Nov 06 '23 04:11 simonw