Home > Net >  Submit Flask form without re-rendering the page
Submit Flask form without re-rendering the page

Time:03-02

I'm building a form with flask, below is the simplified version of my flask server

app = Flask(__name__)

@app.route("/", methods = ["POST", "GET"])
def main_page():
    if request.method == "POST": 
        # some cool stuff

    return render_template("main.html") 

if __name__ == "__main__":
    app.debug = True
    app.run()

The problem is that it re-renders the page when the user submits the form, jumping to the top of the page. That makes the user experience kinda bad. How to get the data of the form without re-rendering the entire page?

CodePudding user response:

If you want to submit the form data, but don't want to completely re-render the page, your only option is to use AJAX.
In the following example, the form data is sent using the Fetch API. The processing on the server remains essentially the same because the form data is submitted in the same format.
However, since there is usually a response in JSON format here, I advise outsourcing the endpoint, so that there is a separation between HTML and JSON routes.

from flask import (
    Flask,
    jsonify,
    render_template,
    request
)

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/upload', methods=['POST'])
def upload():
    # Same cool stuff here.
    print(request.form.get('data'))

    return jsonify(message='success')
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Index</title>
  </head>
  <body>

    <form name="my-form" method="post">
      <input type="text" name="data" />
      <input type="submit" />
    </form>

    <script type="text/javascript">
      (uri => {
        // Register a listener for submit events.
        const form = document.querySelector('form[name="my-form"]');
        form.addEventListener('submit', evt => {
          // Suppress the default behavior of the form.
          evt.preventDefault();
          // Submit the form data.
          fetch(uri, {
            method: 'post',
            body: new FormData(evt.target)
          }).then(resp => resp.json())
            .then(data => {
              console.log(data);
              // Handle response here.
            });
          // Reset the form.
          evt.target.reset();
        });
      })({{ url_for('upload') | tojson }});
    </script>

  </body>
</html>
  • Related