Multiple instances of the same form field

2019-03-30 01:05发布

问题:

I have invite form with two fields defined as person and email as follows:

class InviteForm(Form):
    person = TextField("person", validators=[validators.Required("Please enter persons name.")])
    email =  EmailField("email", validators=[validators.Required("Please enter valid email."), validators.Email("Please enter valid email.")])

    def validate(self):
        return validate_form(self)

Where validate_form function is a cusotm validator which check few conditions for invite.

My requirement is to allow users to invite more than one person at a time. To achieve this I have added jquery function which replicates these fields in html form and allow to invite multiple people.

But the problem is in my view function when I extract results from post request it gives only first persons information. How can I get all the persons details. My view is defined as follows:

@app.route("/invite", methods=["GET", "POST"])
def invite():
   invite_form = InviteForm()
   if invite_form.validate_on_submit():
       print invite_form.person
       print invite_form.email

This gives only one field, instead of array of fields.

Is this possible with python wtf? How?

回答1:

What you're looking for is FormField which lets you build a list of the WTF Fields (or groups even).

Here's a simple example-- it'll render three string fields as a html list because that's the minimum required. If you want to add extras via javascript, then just adhere to the same naming scheme, in the case below, a fourth would have a name of person-3.

from flask import Flask, render_template_string
from flask.ext.wtf import Form
from wtforms import FieldList, StringField

app = Flask(__name__)
app.secret_key = 'TEST'


class TestForm(Form):
    person = FieldList(StringField('Person'), min_entries=3, max_entries=10)
    foo = StringField('Test')


@app.route('/', methods=['POST', 'GET'])
def example():
    form = TestForm()
    if form.validate_on_submit():
        print form.person.data
        ## [u'One', u'Two', u'Three']

    return render_template_string(
        """
            <form method="post" action="#">
            {{ form.hidden_tag() }}
            {{ form.person }}
            <input type="submit"/>
            </form>
        """, form=form)


if __name__ == '__main__':
    app.run(debug=True)