When unchecked, checkboxes are not sent by your browser. Therefore if for example you want to forward the request to an API without any specific parsing, your Flask app does not have any information about the input. It means that from the API point of view, you don’t know if the user did not update the value or have unchecked the input.

To resolve this dilemma, the hack is to render two inputs with the same name:

  1. the checkbox field
  2. an hidden field holding the expected value when the checkbox is unchecked.
<input type="checkbox" name="my_field" value="foo">
<input type="hidden" name="my_field" value="bar">

When the user submit the form, if the checkbox is checked, the browser will send the two values: the checkbox one and the hidden one. Now if the checkbox is not checked only the hidden value is returned.

The hack is here, when retrieving form values from Flask (request.form.to_dict()) it will by default return the first value of each field (see werkzeug MultiDict doc). It means that if you have multiple inputs with the same name only the first returned input in the page is used. In our case it solve the lack of information when unchecked without any specific parsing.