Add input fields dynamically with wtforms Add input fields dynamically with wtforms flask flask

Add input fields dynamically with wtforms


WTForms has a meta-field called FormField and another meta-field called FieldList. These two combined together will get you what you want:

class AddressEntryForm(FlaskForm):    name = StringField()class AddressesForm(FlaskForm):    """A form for one or more addresses"""    addresses = FieldList(FormField(AddressEntryForm), min_entries=1)

To create entries in the AddressesForm, simply use a list of dictionaries:

user_addresses = [{"name": "First Address"},                  {"name": "Second Address"}]form = AddressesForm(addresses=user_addresses)return render_template("edit.html", form=form)

Then, in your template, simply loop over the sub-forms:

{% from 'your_form_template.jinja' import forms %}{% for address_entry_form in form.addresses %}    {{ address_entry_form.hidden_tag() }}    {# Flask-WTF needs `hidden_tag()` so CSRF works for each form #}    {{ forms.render_field(address_entry_form.name) }}{% endfor %}

WTForms will automatically prefix the names and the IDs correctly, so when you post the data back you will be able to just get form.addresses.data and get back a list of dictionaries with the updated data.


Sean Vieira's answer works great for StringFields (previously TextField), but things get a little trickier for dynamic SelectFields. For anyone interesting in how to implement dynamic SelectFields with wtforms, see https://stackoverflow.com/a/57548509/7781935