Dynamically add input fields using wtforms

I'm not quite sure how this question fits. I hope I get there.

For example, I have a table full of addresses on the page. Their number is dynamic (it can be 5 or 10 or any other quantity). And I want the ability to edit them on one page.

My approach was to create a form with wtforms to edit a single address and multiply this in jinja2 for loop and add to the html name and id loop.index0 from itereation, so I can extract each row of data manually and return it to my form when I I want to evaluate it.

So the form for this example would look like this:

 class AdressForm(Form): name = TextField() 

So, now my aproach template looks like this (split into one input field):

 {% for address in addresses %} {{ forms.render_field(addressform.name, id = "name_" ~ loop.index0, name = "name_" ~ loop.index0, value = address.name) }} {% endfor %} 

(forms.render_field is just a macro to indicate the correct classes for the wtforms field function, as they are used in many tutorials)

So this does not work, since you cannot pass the name parameter manually for the field function, since wtforms create the name html parameter from variblameame from the inline form.

So, there is a way to add a prefix or postfix to the name of the form I want to display. Or is this an XY problem, and my approach is not true.

or I do it all on my own (I really try to avoid this)

+12
source share
2 answers

WTForms has a FormField meta field and another FormField meta field. These two combined will get 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 AddressesForm, just use the dictionary list:

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

Then, in your template, just loop over the 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 correctly add prefixes to names and identifiers, so when you send the data back, you can simply get form.addresses.data and get a list of dictionaries with updated data.

+24
source

Sean Vieira's answer works fine for StringFields (formerly TextField ), but with dynamics, things get a little more complicated than SelectFields . For those interested in how to implement dynamic SelectFields with wtforms , see fooobar.com/questions/8646066 / ...

+1
source

Source: https://habr.com/ru/post/1212846/


All Articles