skip to Main Content

I’ve been struggling with this one and I can’t get a proper answer.

Disabling the button after click doesn’t help because it needs to be working in case of not valid request.

Shouldn’t the form already being handling this sort of situations since in app.py I redirect after form.validate_on_submit()

Any idea on how to stop form from being submitted twice on quick submit button presses?

register.html:

    {% extends "layout.html" %}

{% block content %}

<div class="mb-5">
    <h2 class="text-center mt-3">Register</h2>

    <form action="/register" method="post" class="mt-3 mb-3" novalidate autocomplete="off">

        {{ form.csrf_token }}

    {# Username #}
        <div class="mb-3">
            {{ form.username.label(class="form-label") }}
      {{ form.username(class="form-control") }}
      {% for error in form.username.errors %}
            <span style="color: red">[{{ error }}]</span>
            {% endfor %}
        </div>

    {# Email #}
        <div class="mb-3">
            {{ form.email.label(class="form-label") }}
      {{ form.email(class="form-control", autocomplete="username", autocapitalize="off") }}
      {% for error in form.email.errors %}
            <span style="color: red">[{{ error }}]</span>
            {% endfor %}
            <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
        </div>

    {# Password #}
        <div class="mb-3">
            {{ form.password.label(class="form-label") }}
      {{ form.password(class="form-control", autocomplete="new-password") }}
            {% for error in form.password.errors %}
            <span style="color: red">[{{ error }}]</span>
            {% endfor %}
        </div>

    {# Passowrd confirm #}
        <div class="mb-3">
            {{ form.confirm.label(class="form-label") }}
      {{ form.confirm(class="form-control", autocomplete="new-password") }}
      {% for error in form.confirm.errors %}
            <span style="color: red">[{{ error }}]</span>
            {% endfor %}
        </div>

    {# Submit button #}
        <div class="d-flex justify-content-center">
    {{ form.submit(class="btn btn-secondary mt-2", id="submit-button")}}
    </div>
    </form>

    <div class="text-center">
        <p class="d-inline me-3">You have an account?</p>
        <a href="{{url_for('login')}}">Login</a>
    </div>
</div>


{% endblock %}

app.py

@app.route("/register", methods=['GET','POST'])
def register():
  form = RegisterForm()

  if form.validate_on_submit():
    
    hashed_password = bcrypt.generate_password_hash(form.password.data)
    new_user = User(username=form.username.data, email=form.email.data.lower(), password=hashed_password)
    db.session.add(new_user)
    db.session.commit()
    return redirect(url_for('login'))
  else:
    print(form.errors.items())
  
  return render_template("register.html", form=form)

Below you can see the terminal

You can see in the terminal the same datas being submitted 3 times, the first time the go to database and the other two times they get rejected by server side validation.

2

Answers


  1. Chosen as BEST ANSWER

    Ok, I found what the problem was. Simply I was putting the javascript outside of the jinja endblock block, on the bottom of the page. Now the javascript works.


  2. To prevent the form from being submitted twice if the user quickly clicks the submit button, you can use a technique known as "form disabling" using JavaScript. Here’s how you can modify your HTML template and JavaScript to achieve this:

    make the register.html:

    {% extends "layout.html" %}
    
    {% block content %}
    
    <div class="mb-5">
        <h2 class="text-center mt-3">Register</h2>
    
        <form action="/register" method="post" class="mt-3 mb-3" novalidate autocomplete="off" id="register-form">
    
            {{ form.csrf_token }}
    
        {# Username #}
            <!-- ... (your existing code) ... -->
    
        {# Submit button #}
            <div class="d-flex justify-content-center">
                {{ form.submit(class="btn btn-secondary mt-2", id="submit-button")}}
            </div>
        </form>
    </div>
    
    <script>
        document.getElementById("register-form").addEventListener("submit", function () {
            document.getElementById("submit-button").disabled = true;
        });
    </script>
    
    {% endblock %}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search