Mohamed Moustafa
Mohamed Moustafa

Reputation: 509

Html form submitting previous choice when I refresh page of Flask web app

In my Flask application, I have a simple form of type POST and 4 radio-buttons options with the same name. When I choose an option and press "next" (a submit-type input), a new page loads with different content but a form of the same type.

The issue is, if I refresh the newly loaded page, the form is submitted with the option having the same value as the previously chosen option.

Form:

<form id="myForm" name="myForm" method="post" >
    <table align="center" cellpadding="10" border="0" style="background-color: antiquewhite;">
        <tr>
            <td rowspan="2"><h3>Is this an <i>origin</i> for the <i>claim?</i></h3></td>
            <td><input type="radio" name="op" id="op1" value="1" >Yes</td>
            <td><input type="radio" name="op" id="op2" value="2" >No</td>
            <td rowspan="2"><input type="submit" value=Next></td>
        </tr>

        <tr>
            <td><input type="radio" name="op" id="op3" value="3" >Invalid Input</td>
            <td><input type="radio" name="op" id="op4" value="4" >Don't Know</td>
        </tr>
    </table>
    </form>

Snippet of Python code dealing with form:

if request.method == 'POST':
            op = request.form.get('op')
            if op:
                if op in ['1', '2', '3', '4']:
                    save_annotation(session.get('claim'),session.get('origin'), op, name)
                    c_url, o_url = get_least_annotated_page(name, session['claim'])

            else:
                c_url = session['claim']
                o_url = session['origin']

else:
    print("NOT POST AND LOGGED IN")
    c_url, o_url = get_least_annotated_page(name)
.
.
.
.
.
return render_template('index.html',t1=c_url, t2=o_url)

I just want to be able to refresh the page without the form being POSTed.

I already tried using

document.getElementById("myForm").reset();

as well as

<body onload="document.myForm.reset();">

and

autocomplete="off"

Full code available here(annotator.py, app/templates/index.html, and app/templates/base.html):

https://github.com/MohamedMoustafaNUIG/AnnotatorVM.git

EDIT:session is just a global variable that I use to store stuff. name is initialised in the beginning of the python code, and save_annotation() and get_least_annotated_page() are functions.

EDIT2: When a new page is loaded, the buttons are all unchecked. Yet when I refresh, an option is submitted. I only noticed by looking through the command line output.

Upvotes: 1

Views: 1996

Answers (3)

Mohamed Moustafa
Mohamed Moustafa

Reputation: 509

I found a working solution. It might need more testing before I am sure, but for now it is working fine.

Basically, Ill keep a variable that will be incremented when the user chooses an option. Ill then compare the value stored in session (server-side) with the version sent in the form by the POST request. If they are the same, then this is a refresh, otherwise it is a normal submit.

Code:

Client-side (index.html)::

<form method="post">
    <table align="center" cellpadding="10" border="0" style="background-color: antiquewhite;">
        <tr>
            <td rowspan="2"><h3>Is this an <i>origin</i> for the <i>claim?</i></h3></td>
            <td><input type="radio" name="op" id="op1" onchange="incAlpha();" value="1" >Yes</td>
            <td><input type="radio" name="op" id="op2" onchange="incAlpha();" value="2" >No</td>
            <td rowspan="2"><input type="submit" value=Next></td>
        </tr>

        <tr>
            <td><input type="radio" name="op" id="op3" onchange="incAlpha();" value="3" >Invalid Input</td>
            <td><input type="radio" name="op" id="op4" onchange="incAlpha();" value="4" >Don't Know</td>
        </tr>
    </table>
        <input type="hidden" id="alpha" name="alpha" value={{alpha}}>
    </form>
<script type="text/javascript">
    var globFlag=true; // use so that the incrementation is only triggered once every page load
    function incAlpha()
    {
        if(globFlag)
        {
            let value= document.getElementById("alpha").value;
            document.getElementById("alpha").value = (parseInt(value)+1)%10;
            globFlag=false;
        }
    }
</script>

Python (Flask) Code:

name = session.get('username')
        alphaFromSession = session.get('alpha')
        if request.method == 'POST':
            op = request.form.get('op')
            alphaFromClient = request.form.get('alpha')
            if op and not (alphaFromSession == alphaFromClient):
                if op in ['1', '2', '3', '4']:
                    save_annotation(session.get('claim'),session.get('origin'), op, name)
                    session['alpha']=alphaFromClient
                    c_url, o_url, src_lst, donePg, totalPg, done, total = get_least_annotated_page(name, session.get('claim'))


.
.
.
.
return render_template('index.html',t1=c_url, t2=o_url,alpha=session.get('alpha'))

Upvotes: -1

djnz
djnz

Reputation: 2050

When you refresh the page the browser will perform the last action, in your case a POST.

The way to avoid this would be to change the return to a redirect instead of render:

if request.method == 'POST':

    ...

    return redirect(url_for('this_view'))

...

Source

Upvotes: 1

McGregor
McGregor

Reputation: 1

You can try:

document.getElementById("op1").prop('checked', false)

this will uncheck the radio button. This can be done to each one.

Upvotes: -1

Related Questions