Returning plt.show() on HTML with Python Flask

Issue

I’m using Python Flask to take input from a simple html file. The HTML asks the user to input a state and when they do that I would like for the output to be a plot.

I have the following code that’s creating the Python Flask but when a user inputs a state, the plot outputs in my Jupyter Notebook file instead of on the HTML page.

I’ve seen methods using Figure() to get the plot to show on the HTML page but I’m not sure how to recreate my current plot using the figure function.

app = Flask(__name__)

@app.route('/')
def form():
    return render_template("flask_form.html")

@app.route('/', methods = ['POST'])
def form_post():
    state = request.form['userinput']
    
    dff = df[df['state'] == state]
    dff['total_icu_beds_7_day_avg'] = dff['total_icu_beds_7_day_avg'].astype(float)
    dff['total_beds_7_day_avg'] = dff['total_beds_7_day_avg'].astype(float)
    dff['inpatient_beds_7_day_avg'] = dff['inpatient_beds_7_day_avg'].astype(float)
    
    pivot = np.round(dff.pivot_table(index = ["collection_week"], values = ["total_icu_beds_7_day_avg", "total_beds_7_day_avg", "inpatient_beds_7_day_avg"], aggfunc = [np.mean]), 0)
    pivot.columns = ['Inpatient 7 day Avg', 'Total Beds 7 day Avg', 'Total ICU Beds 7 day Avg']
    pivot = pivot.reset_index()
    
    x = pivot['collection_week']
    y1 = pivot['Inpatient 7 day Avg']
    y2 = pivot['Total Beds 7 day Avg']
    y3 = pivot['Total ICU Beds 7 day Avg']
    
    title = str(state + " State Staffed Beds")

    plt.figure(figsize=(16,6))
    plt.plot(x, y1, label = 'Inpatient AVG', color = 'blue')
    plt.plot(x, y2, label = 'Total Beds AVG', color = 'red')
    plt.plot(x, y3, label = 'Total ICU Beds AVG', color = 'cyan')
    plt.legend()
    plt.title(title, fontweight = 'bold')
    plt.ylabel("Number of Staffed Beds")
    plt.xlabel("Date")
    plt.show()

Here’s my HTML code, I know the plot needs to be in the output but not sure how to code it:

<!DOCTYPE html>
<html lang="en">
<body>
    <h1>Hospital Capacity by State</h1>
    <p>Enter the abbreviation of your desired state:</p>
    <form action="." method="POST">
        <input type="text" name="userinput">
        <input type="submit" name="my-form" value="Send">
        <output> </output>
    </form>
</body>
</html>

Solution

The Python Flask code:

app = Flask(__name__)

@app.route('/')
def form():
    return render_template("flask_form_plot.html")

@app.route('/', methods = ['POST'])
def form_post():
    state = request.form['userinput']
    
    dff = df[df['state'] == state]
    dff['total_icu_beds_7_day_avg'] = dff['total_icu_beds_7_day_avg'].astype(float)
    dff['total_beds_7_day_avg'] = dff['total_beds_7_day_avg'].astype(float)
    dff['inpatient_beds_7_day_avg'] = dff['inpatient_beds_7_day_avg'].astype(float)
    
    pivot = np.round(dff.pivot_table(index = ["collection_week"], values = ["total_icu_beds_7_day_avg", "total_beds_7_day_avg", "inpatient_beds_7_day_avg"], aggfunc = [np.mean]), 0)
    pivot.columns = ['Inpatient 7 day Avg', 'Total Beds 7 day Avg', 'Total ICU Beds 7 day Avg']
    pivot = pivot.reset_index()

    x = pivot['collection_week']
    y1 = pivot['Inpatient 7 day Avg']
    y2 = pivot['Total Beds 7 day Avg']
    y3 = pivot['Total ICU Beds 7 day Avg']
    
    plt.figure(figsize=(16,6))
    plt.plot(x, y1, label = 'Inpatient AVG', color = 'blue')
    plt.plot(x, y2, label = 'Total Beds AVG', color = 'red')
    plt.plot(x, y3, label = 'Total ICU Beds AVG', color = 'cyan')
    plt.legend()
    plt.title(str(state) + " State Staffed Beds", fontweight = 'bold')
    plt.ylabel("Number of Staffed Beds")
    plt.xlabel("Date")

    img = io.BytesIO()
    plt.savefig(img, format = 'png')
    img.seek(0)
    plot_data = urllib.parse.quote(base64.b64encode(img.read()).decode())
    return render_template('flask_form_plot.html', plot_url = plot_data)

The HTML code:

<!DOCTYPE html>
<html lang="en">
<body>
    <h1>Hospital Capacity by State</h1>
    <p>Enter the abbreviation of your desired state:</p>
    <form action="." method="POST">
        <input type="text" name="userinput">
        <input type="submit" name="my-form" value="Send">
        <br>
        <br>
        <output> <img src="data:image/png;base64, {{ plot_url }}" width="1000" height="500" alt="graph"> </output>
    </form>
</body>
</html> 

Answered By – amatof

Answer Checked By – Dawn Plyler (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.