Add fields dynamically to WTForms form
flask, flask-wtforms, python, wtforms
Solution
Use `setattr` to add new fields as attributes of the form class. This will cause WTForms to set up the field correctly instead of keeping the unbound field.
# form class with static fields
class MyForm(FlaskForm):
name = StringField('static field')
record = {'field1': 'label1', 'field2': 'label2'}
# add dynamic fields
for key, value in record.items():
setattr(MyForm, key, StringField(value))
In the template you can iterate over the fields using the `attr` filter.
{% for key, value in record.items() %}:
{{ form|attr(key)() }}
{% endfor %}
Problem
I want to define a form class with fields based on a dict of `name: label`. I tried the following, which nearly worked. However, rendering the fields in a template gave `AttributeError: 'UnboundField' object has no attribute '__call__'`. How can I dynamically add fields to a form? ``` def build_form(name, record): class ContactForm(FlaskForm): name = StringField(name) fieldlist = {} for key, value in record.items(): fieldlist[key] = StringField(key) @app.route('/', methods=['GET', 'POST']) def showform(): form = ContactForm(request.form) if request.method == 'POST': return 'form processed' return render_template('cardcompare.tpl', record=record, form=form) ``` ``` <form method=post> {{ form.name() }} {% for key, value in record.items() %} {{ form.fieldlist[key]() }} {% endfor %} <input type=submit value=Register> </form> ```