Skip to content

Instantly share code, notes, and snippets.

@doobeh
Created January 20, 2016 19:19
Show Gist options
  • Save doobeh/503819eff1661cff612d to your computer and use it in GitHub Desktop.
Save doobeh/503819eff1661cff612d to your computer and use it in GitHub Desktop.
Persuading WTForms to Generate Checkboxes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WTForms takes the pain out of handling forms and validation, you define your form,
tell it what validation checks the data needs to pass, then WTForms uses it's
widgets to generate the html.
A common problem you'll face is "Multiple select fields suck, they are confusing--
how can I show the user a nice list of checkboxes instead?"
The answer is to tell WTForms to use a different widgets to render it's html. Lets
first show how we'd render a simple SelectMultipleField form:
from flask import Flask, render_template_string
from wtforms import SelectMultipleField, Form
app = Flask(__name__)
data = [('value_a','Value A'), ('value_b','Value B'), ('value_c','Value C')]
class ExampleForm(Form):
example = SelectMultipleField(
'Pick Things!',
choices=data
)
@app.route('/')
def home():
form = ExampleForm()
return render_template_string('<form>{{ form.example }}</form>',form=form)
if __name__ == '__main__':
app.run(debug=True)
Voila, we have a basic horrible to use multiple select field, now we just need to change
how WTForms renders that SelectMultipleField by telling it to use a couple of different
widgets to produce our checkboxes
from wtforms import widgets
class ExampleForm(Form):
example = SelectMultipleField(
'Pick Things!',
choices=data,
option_widget=widgets.CheckboxInput(),
widget=widgets.ListWidget(prefix_label=False)
)
And that's it-- you'll be rendering check boxes for each of the sets of data, congratulations!
@wgwz
Copy link

wgwz commented Jan 22, 2016

@doobeh. Hey. This is super nice, and I want to use the feature. But I am having some overflow issues with bootstraps js modal. Obviously I want the forms in the modal. But the check boxes overflow, past the bottom edge of the modal. I've verified that standard wtf-forms without widgets, do not overflow in the bootstrap modals. Do you any suggestions for how to work around this? I am using the flask-bootstrap extension (for what it is worth). I'll share more specific version info if you like.

@wgwz
Copy link

wgwz commented Jan 22, 2016

Well, for posterity the issue is that wtf.quick_form tool in Flask does not render the field properly inside of the modal. But build the field manually inside the bootstrap modal as:

<div class="row">
    <form>
        {{ modal_forms[item|string].csrf_token }}
        {% if 'sizes' in modal_forms[item|string] %}
            {{ modal_forms[item|string].sizes }}
        {% endif %}
        {% if 'sides' in modal_forms[item|string] %}
            {{ modal_forms[item|string].sides }}
        {% endif %}
        {% if 'toppings' in modal_forms[item|string] %}
            {{ modal_forms[item|string].toppings }}
        {% endif %}
        {% if 'choices' in modal_forms[item|string] %}
            {{ modal_forms[item|string].choices }}
        {% endif %}
        {{ modal_forms[item|string].submit }}
    </form>
</div>

And there will be no overflow issue. The fields sides, toppings and choices are all SelectMultipleField's with the widgets above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment