0

Here's the section of code where i'm generating a plot:

graph = df.plot(x='date', y='close')
fig = graph.get_figure()
filepath = 'static/images/graph.png'
fig.savefig(filepath)

return render_template('search_result.html')

I'm defining my static path in the top of my Flask file like this:

app = Flask(__name__, static_folder='path/to/static/folder')

Here's my file directory setup:

Main Folder
  - Static
    -- Images
      --- Graph.png
  - Templates
  - app.py

In my HTML template, i'm currently just doing this:

<img src="{{ url_for('static', filename = 'graph.png') }}"> ... however it's only displaying an older image. I'm rewriting over the image every time the function is called.

I understand passing variables to HTML using jinja however i'm unsure how to do it with an image path.

Could anyone help me out?

Harrison
  • 5,095
  • 7
  • 40
  • 60

2 Answers2

0

You need to create a route that connects to a send from directory invocation from Flask. So you basically create an image with a src attribute to your Flask route that sends the image using send_from_directory. That's to send from any arbitrary folder beyond the default static folder. When I send Matplotlib images I add a query string that is the file modification time for the image file. There's a Python library to get that from a path and you can see some usage below. There's a special meta mode for html to force a refresh each time an image is used but it didn't work for me for reasons I couldn't explain and I wound up using the mod time to bypass the browser cache.

First off I render a template with the following parameters...

# Acquire image modification times to use as query strings to bypass image caching.
modificationTime = os.path.getmtime( "%s/%s" % ( model.getImagesSubfolder( ) , imageFile ) )
return render_template( 'plotsPage.html' , fileName=imageFile , modTimes=modificationTime )

Then my plotsPage.html template file has a the following tag, which creates the necessary query string with the mod time just looked up on the server side...

<img src="{{ url_for( 'sendPlotImage' , filename=fileName , t=modTime ) }}">

Then the url I'm connecting to serves the actual image using the send_from_directory. I have a view model that gives me the subfolder beneath my app where my images can be retrieved on a user by user basis with session state and all that.

@flaskApp.route( '/Images/<filename>' , methods=['GET'] )
def sendPlotImages( filename ) :   
    # Image file not generated, send placeholder instead to denote file does not exist.
    if not os.path.isfile( "%s/%s" % ( model.getImagesSubfolder( ) , filename )  ) :
        return send_from_directory( "static" , placeHolderImage )

    return send_from_directory( model.getImagesSubfolder( ) , filename )
jxramos
  • 7,356
  • 6
  • 57
  • 105
  • This didn't work. Returned an error. Would it be possible to edit your example to fit the code I provided? I'm still struggling with this. – Harrison Jul 25 '17 at 03:18
  • the code I provided has to be adapted to your circumstances, for example the `model.getImagesSubfolder()` and `placeHolderImage` are specific to my application but are provided to get you to think about structuring these things to what you have. What was the error you got? – jxramos Jul 25 '17 at 04:15
  • I was able to solve this in a different way thanks though! – Harrison Jul 25 '17 at 04:16
0

you should pass img as bytes.

%pylab
from io import BytesIO
x = np.linspace(0, np.pi, 100)
y = np.sin(x)
plt.plot(x, y)
fig = plt.gcf()
buffer = BytesIO
fig.canvas.print_png(buffer)
buffer.seek(0)

and you can use send_file to send the img:

from flask import send_file
@app.route('/img')
def images():
    return send_file(buffer, mimetype="image/png")
linw1995
  • 166
  • 1
  • 8
  • Hmm. So I wouldn't be rendering the template? Would it be possible to edit your example code to fit my code that I provided. My function doesn't have a route currently. It's just a processing function. – Harrison Jul 24 '17 at 02:06
  • you can use render the img. I prefer this way to do it. – linw1995 Jul 24 '17 at 02:16
  • 2
    How would I send the image to the HTML template though. – Harrison Jul 24 '17 at 02:28