0

To setup a simple html front-end and python flask back-

  1. Create a html script (index.html) and save D:\Projects\test_backgroundtask\templates\views

<html>
    <section>
      <div>
        <h>Test background task</h>
      </div>
    </section>
</html>
  1. Create a python script and save D:\Projects\test_backgroundtask:

Code

import pandas as pd
from flask import Flask, render_template, request
    
    
    app = Flask(__name__)
    
    
        
    @app.route('/', methods=['GET'])
    def index():
        return render_template('views/index.html')
    
    @app.route('/post', methods=['POST'])
    def post():
        return "recived: {}".format(request.form)
    
    if __name__ == "__main__":
        app.run( port = '5004')

To create a background task, flask has a package called flask_executor Updated python script using excutor to create a background

    from flask import Flask, render_template, request
    import pandas as pd
    from flask_executor import Executor
    global input_val
    
    app = Flask(__name__)
    
    def background_task_func(input_val):
        if input_val==1:
            data = {'Name': ['Tom', 'Joseph', 'Krish', 'John'], 'Age': [20, 21, 19, 18]}  
            test_val= pd.DataFrame(data)
        print(test_val)
        
    @app.route('/', methods=['GET'])
    def index():
        global input_val
        input_val=1
        executor.submit(background_task_func,input_val)
        return render_template('views/index.html')
    
    @app.route('/post', methods=['POST'])
    def post():
        return "recived: {}".format(request.form)
    
    if __name__ == "__main__":
        executor = Executor(app)
        app.run( port = '5004')

Required Output:

Once the results are completed, the table containing test_val should be displayed.

NB: the html page index.html is currently being viewed by the user and it has other tables already displayed. The user is also interacting with other buttons on this page.

Additional Info

NB: I use Django within <script>...</script> in my html script.

An example of how I used it to toggle a table or button:

  <script>
    function myFunctionDemoFeat() {
      var x = document.getElementById("demofeatDIV");
      if (x.style.display === "none") {
        x.style.display = "block";
      } else {
        x.style.display = "none";
      }
    }
   </script>
davidism
  • 121,510
  • 29
  • 395
  • 339
Sade
  • 450
  • 7
  • 27
  • I am currently confused on how to pass test_val to index.html. Suggestions around this will be much appreciate. I will be able follow through from this point onwards. – Sade Jul 12 '21 at 09:51
  • I have simplified the desired output above. – Sade Jul 12 '21 at 09:52
  • I have example using celery but have not come across one with using flask executor, https://stackoverflow.com/questions/44922876/how-can-i-render-html-page-of-django-after-the-background-celery-task-is-complet . This can be a starting point. – Sade Jul 12 '21 at 10:49
  • Its appears that they call return render(..) again, in the function where the new values are generated. Is this the right way to do it? – Sade Jul 12 '21 at 10:57

1 Answers1

0

Python script

from flask import Flask, render_template, request
import pandas as pd
from flask_executor import Executor
global input_val
global test_val
app = Flask(__name__)

def background_task_func(input_val):
    global test_val
    data = {'Name': ['Tom', 'Joseph', 'Krish', 'John'], 'Age': [20, 21, 19, 18]}  
    test_val= pd.DataFrame(data)
    if test_val.shape[0]>1:
        print(test_val)
        return render_template('views/index.html',tables=[test_val.to_html(classes='data')])
    
@app.route('/', methods=['GET'])
def index():
    executor.submit(background_task_func,input_val)
    return render_template('views/index.html',tables=[test_val.to_html(classes='data')])

@app.route('/post', methods=['POST'])
def post():
    return "recived: {}".format(request.form)

if __name__ == "__main__":
    data ={'Name': [], 'Age': []}  
    test_val= pd.DataFrame(data)
    input_val=1
    executor = Executor(app)
    
    app.run( port = '5004')

Html code

<html>
    <section>
      <div>
        <h>Test background task</h>
      </div>
      
      <div id="demofeatDIV" class="w3-container">
        <table class="w3-table-all w3-tiny">
            <tbody>
            <tr><th>Results</th></tr>
            {% for table in tables %}
                 {{ table|safe }}
            {% endfor %}
            </tbody>
       </table>
       <br>
     </div> 
    </section>
</html>

For a simple test example , this method will be fine. However, if there are other data being displayed, the disadvantage of using this method is that I need to refresh the entire page, this results in reloading the previous tables. The alternative solution is to use sockets. My solution in Flask socketio | Emitting a pandas dataframe from a background task using Flask executor to an Html script resolve this issue.

Sade
  • 450
  • 7
  • 27
  • To create the table from a dataframe, I referred to the link https://stackoverflow.com/questions/52644035/how-to-show-a-pandas-dataframe-into-a-existing-flask-html-table – Sade Jul 12 '21 at 12:34