Gimdalf
Gimdalf

Reputation: 77

wtforms submitting wrong form

I'm making a web-app in Flask and on a page I have a few forms, when I click the submit button for one form (the one called 'UsedBatch'), it ends up submitting it as if it's the other form (the one called 'NewBatch') and I can't see why. The form definitions are shown below:

class NewBatch(FlaskForm):
    quantity = IntegerField('Number of items:', validators=[DataRequired()])
    date = DateField('Date:', default = date.today(), validators=[DataRequired()])
    submit = SubmitField('Submit')

class UsedBatch(FlaskForm):
    quantity = IntegerField('Number of items used:', validators=[DataRequired()])
    date = DateField('Date:', default = date.today(), validators=[DataRequired()])
    used_by = StringField('Used by:')
    submit = SubmitField('Submit')

Before they're run through the template, some attributes of the forms are added and then they are defined as shown:

for items in items_list:
    setattr(NewBatch, 'item_no', IntegerField(default = items.item_no))
    setattr(UsedBatch, 'item_no', IntegerField(default = items.item_no))
    processed_items_list.append({'item_no':items.item_no, 'quantity':items.quantity, 'items':items.items, 'batch_form':NewBatch(), 'used_form':UsedBatch()})
used_form = UsedBatch()
batch_form = NewBatch()

And lastly, the code for the forms in the template is shown below, I iterate through a list (the 'processesd_items_list' shown above_ where each element in the list has an attached form, the iterable in this case is called items. the first form (the UsedBatch) is:

<form method="POST">
    {{ items['used_form'].date.label }}{{ items['used_form'].date(class="uk-input") }}
    {{ items['used_form'].quantity.label }}{{ items['used_form'].quantity(class="uk-input") }}
    {{ items['used_form'].used_by.label }}{{ items['used_form'].used_by(class="uk-input") }}
    {{ items['used_form'].hidden_tag.label }}{{ items['used_form'].hidden_tag() }}
    {{ items['used_form'].submit() }}
</form>

and the second form (the NewBatch) is:

<form method="POST">
    {{ items['batch_form'].date.label }}{{ items['batch_form'].date(class="uk-input") }}
    {{ items['batch_form'].quantity.label }}{{ items['batch_form'].quantity(class="uk-input") }}
    {{ items['batch_form'].hidden_tag.label }}{{ items['batch_form'].hidden_tag() }}
    {{ items['batch_form'].submit() }}
</form>

Can anyone see why it would submit NewBatch over UsedBatch? When I just add the lines:

if batch_form.validate_on_submit():
    print('Batch submitted')
if used_form.validate_on_submit():
    print('Usage submitted')

It returns "Batch submitted" instead of "Usage submitted" when the UsedBatch form is submitted. Can anyone help point out why? Thanks!

Upvotes: 0

Views: 389

Answers (1)

Kenny Aires
Kenny Aires

Reputation: 1438

Adding a filter on your POST route should fix it, try the following:

if batch_form.submit.data and batch_form.validate(): # notice the order 
    print('Batch submitted')
if used_form.submit.data and used_form.validate(): # notice the order
    print('Usage submitted')

When you call form.validate_on_submit(), it checks if form is 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., batch_form.submit.data).

ref: Multiple forms in a single page using flask and WTForms

Upvotes: 1

Related Questions