flask-bootstrap with two forms in one page flask-bootstrap with two forms in one page flask flask

flask-bootstrap with two forms in one page


Define this two SubmitField with different names, like this:

class Form1(Form):    name = StringField('name')    submit1 = SubmitField('submit')class Form2(Form):    name = StringField('name')    submit2 = SubmitField('submit')

Then in view.py:

....form1 = Form1()form2 = Form2()if form1.submit1.data and form1.validate_on_submit():  # notice the order ....if form2.submit2.data and form2.validate_on_submit():  # notice the order ....

Now the problem was solved.

If you want to dive into it, then continue read.

Here is validate_on_submit():

    def validate_on_submit(self):        """        Checks if form has been submitted and if so runs validate. This is        a shortcut, equivalent to ``form.is_submitted() and form.validate()``        """        return self.is_submitted() and self.validate()

And here is is_submitted():

    def is_submitted(self):        """        Checks if form has been submitted. The default case is if the HTTP        method is **PUT** or **POST**.        """        return request and request.method in ("PUT", "POST")

When you call form.validate_on_submit(), it check if form has been submitted by the HTTP method no matter which submit button was clicked. So the little trick above is just add a filter (to check if submit has data, i.e., form1.submit1.data).

Besides, we change the order of if, so when we click one submit, it only call validate() to this form, preventing the validation error for both form.

The story isn't over yet. Here is .data:

@propertydef data(self):    return dict((name, f.data) for name, f in iteritems(self._fields))

It return a dict with field name(key) and field data(value), however, our two form submit button has same name submit(key)!

When we click the first submit button(in form1), the call from form1.submit1.data return a dict like this:

temp = {'submit': True}

There is no doubt when we call if form1.submit.data:, it return True.

When we click the second submit button(in form2), the call to .data in if form1.submit.data: add a key-value in dict first, then the call from if form2.submit.data: add another key-value, in the end, the dict will like this:

temp = {'submit': False, 'submit': True}

Now we call if form1.submit.data:, it return True, even if the submit button we clicked was in form2.

That's why we need to define this two SubmitField with different names. By the way, thanks for reading(to here)!

Thanks for nos's notice, he add an issue about validate(), check the comments below!