skip to Main Content

When submitting a form in the website, it saves the data inputted after submitting and if you reload or reopen the website, it sends a POST request and then immediately send the same data to the database.

Here are my codes:
Python

from datetime import datetime
from flask import Flask, render_template, request, flash, redirect, url_for
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
app.config["SECRET_KEY"] = "xDxDxD"
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///data.db"
db = SQLAlchemy(app)


class Form(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(80))
    last_name = db.Column(db.String(80))
    email_add = db.Column(db.String(150))
    date = db.Column(db.Date)
    occupation = db.Column(db.String(80))


@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "POST":
        first_name = request.form["first_name"]
        last_name = request.form["last_name"]
        email_add = request.form["email"]
        date = request.form["date"]
        date_obj = datetime.strptime(date, "%Y-%m-%d")
        occupation = request.form["occupation"]

        form = Form(first_name=first_name, last_name=last_name, email_add=email_add, date=date_obj, occupation=occupation)
        db.session.add(form)
        db.session.commit()
        flash(f"{first_name}, your form was submitted successfully", "success")

    return render_template("index.html")


if __name__ == "__main__":
    with app.app_context():
        db.create_all()
        app.run(debug=True, port=5001)

HTML code:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title>Job Form</title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    </head>
    <body>
        <div class="container">
            <h1 class="mt-4 mb-4">Job Application Form</h1>
            <form method="post">
                <div class="form-group mb-4">
                    <label for="first_name">First Name:</label>
                    <input class ="form-control" type="text" id="first_name" name="first_name" required>
                </div>
                <div class="form-group mb-4">
                    <label for="last_name">Last Name:</label>
                    <input class ="form-control" type="text" id="last_name" name="last_name" required>
                </div>
                <div class="form-group mb-4">
                    <label for="email">Email:</label>
                    <input class ="form-control" type="email" id="email" name="email" required>
                </div>
                <div class="form-group mb-4">
                    <label for="date">Available Start Date:</label>
                    <input class ="form-control" type="date" id="date" name="date" required>
                </div>
                <div class="form-group mb-4">
                    <label>Current Occupation:</label>
                    <br>
                    <div class="btn-group-vertical" id="occupation">
                        <input class="btn-check form-control" type="radio" id="employed" name="occupation" value="employed" required>
                        <label class="btn btn-outline-secondary" for="employed">Employed</label>

                        <input class="btn-check form-control" type="radio" id="unemployed" name="occupation" value="unemployed" required>
                        <label class="btn btn-outline-secondary" for="unemployed">Unemployed</label>

                        <input class="btn-check form-control" type="radio" id="self_employed" name="occupation" value="self-employed" required>
                        <label class="btn btn-outline-secondary" for="self_employed">Self-Employed</label>

                        <input class="btn-check form-control" type="radio" id="student" name="occupation" value="student" required>
                        <label class="btn btn-outline-secondary" for="student">Student</label>
                    </div>
                </div>
                <button class="btn btn-secondary mb-4" type="submit">Submit</button>
                {% if messages %}
                {% with messages = get_flashed_messages() %}
                <div class="alert alert-success">
                    {% for message in messages %}
                        {{ message }}
                    {% endfor %}
                </div>
                {% endwith %}
                {% endif %}
            </form>
        </div>
        <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
    </body>
</html>

I tried removing the script in the html, the form variable, I also tried having a request.method for "GET" but when trying to debug the program, every time I reload the website it always sends a "POST" request.

3

Answers


  1. Chosen as BEST ANSWER

    To fix this problem, what I did was return a redirect method to the same route, to have a "GET" method in the "/" index instead of "POST" after submitting. Cheers to Random Cosmos in the comments.


  2. In order to send a different type of request from your form, you need to change the method attribute in the HTML:
    https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form

    I’m not really sure why your form is being submitted multiple times (maybe try clearing your form on submit), but your database and API probably shouldn’t allow you to create multiple records.

    I would create a unique constraint on the email field in your table and/or add a check that no user with that email already exists before creating a new record.

    Login or Signup to reply.
  3. Since nobody really explained what is happening here:

    The problem is a well known one. To fix it, we need to Post -> Redirect -> Get to solve it.

    Basically, if we just POST and the user reloads, it will reload the last request (which was POST).

    After we process the POST request, on the server-side, send a response that is a redirect to a GET request (HTTP 303 – https://en.wikipedia.org/wiki/HTTP_303). Then, when the user reloads the page the last request was a GET and not a POST. This will fix it.

    The Wikipedia page has a nice explanation with diagrams: https://en.wikipedia.org/wiki/Post/Redirect/Get

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search