Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add fields dynamically to WTForms form

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>
like image 306
Omniver Avatar asked May 09 '17 02:05

Omniver


People also ask

How do I add a dynamic field to a 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.

How do you use a flask form?

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.


1 Answers

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 %}
like image 50
Feodoran Avatar answered Sep 24 '22 00:09

Feodoran