0

I am attempting to make an app where a user can upload a CSV file of data and view the data thru the browser on a different flask route which would also a show the plot of the data.

I having issues in my code trying to show the plot of the data. (referencing the static file .png) I can get the pandas dataframe to HTML to work, but in my table.html file I am trying to reference a png plot created with matplot lib and saved to a static directory.

<img src="{{url_for('static', filename=filename)}}" />

All of this experimenting is due to cache issues with the browser so I am creating a unique filename with next_file_name function, and I think this is where I am getting screwed up in the HTML & Jinja trying to reference this unique file name.. I am hoping that a unique filename may be a fix for the cache issues I am observing. The png files are saving properly with the function plot0, plot1, plot2, plot3, etc...

I was hoping to be able to create something where I can repeat the process over & over of analyzing new data and getting retrieving a fresh new plot of the data. Any tips help, thanks

from flask import Flask, make_response, request, render_template
from werkzeug.utils import secure_filename
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import time



app = Flask(__name__, static_url_path='/static')

num = 0

def next_file_name(num):
    return 'static/plot%d.png' % num



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

@app.route('/transform', methods=["POST"])
def transform_view():
    global num

    f = request.files['data_file']
    filename = secure_filename(f.filename)
    f.save(filename)

    df = pd.read_csv(filename, index_col='Date', parse_dates=True)

    OAT = pd.Series(df['OAT'])
    RAT = pd.Series(df['RAT'])
    MAT = pd.Series(df['MAT'])

    df_OATrat = (OAT - RAT)
    df_MATrat = (MAT - RAT)

    plt.scatter(df_OATrat,df_MATrat, color='grey', marker='+')
    plt.xlabel('OAT-RAT')
    plt.ylabel('MAT-RAT')
    plt.title('Economizer Diagnostics')
    plt.plot([0,-18],[0,-18], color='green', label='100% OSA during ideal conditions')
    plt.plot([0,20],[0,5], color='red', label='Minimum OSA in cooling mode')
    plt.plot([0,-38],[0,-9.5], color='blue', label='Minimum OSA in heating mode')
    plt.plot([0,0],[-20,10], color='black')
    plt.plot([-30,20],[0,0], color='black')
    #plt.legend()
    plt.text(-3, -28, time.ctime(), fontsize=9)

    pic = next_file_name(num)
    plt.savefig(pic)

    num+=1

    resp = make_response(render_template('table.html', tables=[df.to_html(classes='data')], titles=df.columns.values, filename='pic'))
    resp.cache_control.no_cache = True
    return resp



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

table.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv='cache-control' content='no-cache'>
    <meta http-equiv='expires' content='0'>
    <meta http-equiv='pragma' content='no-cache'>
    <title>Title</title>
</head>
<body>
    <h1>Economizer Data Plot</h1>
    <img src="{{url_for('static', filename=filename)}}" />
    </form>
    {% for table in tables %}
                {{ table|safe }}
    {% endfor %}

</body>
</html>
bbartling
  • 3,288
  • 9
  • 43
  • 88

2 Answers2

0

You made pic a string instead of using it's value

... filename=pic
Buckeye14Guy
  • 831
  • 6
  • 12
  • Thanks for the post. I tried this, but I get a 404 error. `127.0.0.1 - - [24/May/2019 15:42:16] "GET /static/static/plot11.png HTTP/1.1" 404 -` The plots are working as expected with a new number added to .png every time submit a new CSV file. Does it look odd in the 404 for `/static/static/` directory? plot11.png exists in my `static/` folder directory. Could I have something wrong in my html file? – bbartling May 24 '19 at 20:46
  • You should probably change the function that creates the file name. `return 'plot%d.png' % num` i.e. remove the static. I think url_for('static') puts the /static in front right away. That's why you have two 'static' in your route. Unless you have another folder called static in your normal static folder – Buckeye14Guy May 25 '19 at 10:08
0

If it's a caching issue, it would be easier to either add automatic cache busting to your image files or disable cache with an after-request callback, which triggers the execution of a function at the end of a request.

@app.after_request
def add_header(response):
    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    response.headers["Pragma"] = "no-cache"
    response.headers["Expires"] = "0"
    response.headers['Cache-Control'] = 'public, max-age=0'
    return response

See this solution for more information.

Gabe
  • 956
  • 7
  • 8