Display a ‘loading’ message while a time consuming function is executed in Flask

I found the purely CSS-dependent loader very useful. It does not depend on external resources:

https://www.w3schools.com/howto/howto_css_loader.asp

enter image description here


Add this to your index.html or js file (I'm assuming you have jQuery here, you could use standard javascript of course.):

<script type="text/javascript">// <![CDATA[
        function loading(){
            $("#loading").show();
            $("#content").hide();       
        }
// ]]></script>

Add this to you html or css file:

div#loading {
    width: 35px;
    height: 35px;
    display: none;
    background: url(/static/loadingimage.gif) no-repeat;
    cursor: wait;
    }

You can get an adequate GIF from http://www.ajaxload.info/. Download and put it into your static folder.

Then change your submission button to call above js function:

<input type="submit" name="anything_submit" value="Submit" onclick="loading();">

and add in a loading and a content div to you base html file:

<body>
    <div id="loading"></div>
    <div id="content">
        <h3>Type anything:</h3>
        <p>
        <form action="." method="POST">
            <input type="text" name="anything" placeholder="Type anything here">
            <input type="submit" name="anything_submit" value="Submit" onclick="loading();">
        </form>
        </p>
    </div>    
</body>

Now when you click 'Submit', the js function should hide your content and display a loading GIF. This will display until your data is processed and flask loads the new page.


This can be done by using a div that contains a 'loading gif' image. When the submit button is clicked, the div is displayed using javascript. To implement this, you can take a look at this website: http://web.archive.org/web/20181023063601/http://www.netavatar.co.in/2011/05/31/how-to-show-a-loading-gif-image-while-a-page-loads-using-javascript-and-css/


This is a bit of an old topic, but I needed to deal with this problem today and came with a solution on my own. I'm running a machine learning model that recieves an image input from the user and does some magic.

Basically this is what I did.

On my index.html file, I called a loading function on my "Submit" button passing the filename, because I was going to use it later:

<form method="post" action="/loading/{{filename}}" 
enctype="multipart/form-data">
    <input type="submit" value="Submit!">
</form>

On Flask, I created a route just to render the loading screen before doing the time consuming task, also passing the filename ahead:

@app.route('/loading/<filename>', methods=['POST'])
def loading_model(filename):
    return render_template ("loading.html", filename=filename)

And then, on loading.html, I render my .gif animation and at the end I redirect the page to the time consuming task function:

<!doctype html>
<head>
    <link rel= "stylesheet" type= "text/css" href= "{{url_for('static',filename='styles/main.css') }}">
</head>

<div id="preloader">
    <div id="status">&nbsp</div>
    <h1 class="ml13">ANALYZING...</h1>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.0.2/anime.min.js> </script>
</div>

<title>Title</title>

<script src="{{url_for('static', filename='main.js')}}"></script>

<script> window.location.replace('/task/{{filename}}'); </script>

And then, final step, back to Flask, call the task function:

@app.route('/task/<filename>', methods=['POST', 'GET'])
def task(filename):
    # Do your stuff
return render_template ("results.html")

By doing this, the gif animation will keep playing whilst the function does its job, and then render the results or the next page you want.

You obviously have to edit the css file so that "preloader" and "status" behave like you wish, this is how I used it:

#preloader {
    background-color: white;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

#status {
    background-image: url("lalala.gif");
    background-repeat: no-repeat;
    width: 800px;
    height: 600px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -400px;
    margin-left: -400px;
}

It worked out for me.