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>
If you want to dynamically add elements, you should have a container where to place them. For instance, a <div id="container"> . Create new elements by means of document. createElement() , and use appendChild() to append each of them to the container.
In this file, you first import the Flask class and the render_template() function from the flask package. You then use the Flask class to create a new application instance called app , passing the special __name__ variable, which is needed for Flask to set up some paths behind the scenes.
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 %}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With