Bill
Bill

Reputation: 666

Flask WTForms How to return Posted FieldList form row data

I am having trouble making a WTF FieldList Submit post the correct data back. I am getting a custom button name back - e.g. frmlist-1-delete but the other posted data is always from the first row added. Here is a very simplified example:

# --- forms ------
class ItemForm(Form):
    username = wtf.StringField()
    delete = wtf.SubmitField('Delete')

class WrapperForm(Form):
    frmlist = wtf.FieldList(wtf.FormField(ItemForm))

# --Route--------
@bp.route("/test33", methods=["GET", "POST"])
@csrf.exempt
def test33():

    if request.method == 'POST':
         return redirect (url_for('sitetest.test33'))

    f1 = forms.ItemForm(username='One')
    f2 = forms.ItemForm(username='Two')
    f3 = forms.ItemForm(username='Three')
    wrapperform = forms.WrapperForm()
    wrapperform.frmlist.append_entry(f1)
    wrapperform.frmlist.append_entry(f2)
    wrapperform.frmlist.append_entry(f3)

    return render_template('/sitetest/test33.html', wrapperform=wrapperform)

# --   template---------
<!DOCTYPE html><html lang="en">
<head><meta charset="UTF-8"><title>Title</title></head>
<body>
<form action="" method="post" >
        {% for frm in wrapperform.frmlist %}
        {{ frm.username.data}} {{ frm.delete }}<br>
    {% endfor %}
</form>
</body></html>

The above renders as:

enter image description here

But, no matter which Delete button is clicked, request.form returns the first username 'One'. Here is a view of posting third row using Pycharm. Notice that the correct auto-generated third button name is returned.

enter image description here

Also unexpectedly {{ frm.username }} did not render the value & I had to add .data to make it work.

Any idea how to get the correct row data back so I can delete it? I really don't want to write a hack to parse the button name and then find the data that way.

Upvotes: 0

Views: 82

Answers (1)

GAEfan
GAEfan

Reputation: 11360

A wtf.SubmitField belongs to the form, not an individual form field, so you are just posting the form when you click one. I am not exactly sure from your description what you are trying to accomplish, but you may need to wrap each in its own form tag, like:

{% for frm in wrapperform.frmlist %}
    <form action="" method="post" name="{{frm}}">       
        {{ frm.username.data}} {{ frm.delete }}
    </form><br>
{% endfor %}

Then, test for form name when processing

Upvotes: 1

Related Questions