Skip to content Skip to sidebar Skip to footer

Embedding An Html Page Inside Flask

Ok, I have managed to create a flask page that shows a bokeh image -- now I have to somehow put that into a template https://gist.github.com/cloudformdesign/a0c5f2e8558ea3b60f0a Wh

Solution 1:

Basically you need to create a view which will serve as static image, and you get the image url from that route.

I haven't got your included library so I'm going to use matplotlib and numpy to simulate what you are trying to attempt. This isn't a FULL solution for you (it's in the simplest working way using 2 views and 1 simple template), but you should be able to understand all the ESSENTIAL techniques which let you finish off your page. I have a few comments and guidelines, and I think the code itself is pretty much self explanatory.

OK, here is the view main.py:

from flask import Flask, render_template, request, send_file
import matplotlib.pyplot as plt
import numpy as np
from StringIO import StringIO

app = Flask(__name__)

@app.route('/plot/')
def plot():
    try:
        # try to get the query string like ?width=xxx&height=xxx
        height = int(request.args.get('height'))
        width = int(request.args.get('width'))
    except ValueError:
        # if height, width not available, set a default value
        height, width = 100, 100
    # I randomly generate the plot which just based on H x W
    # you should be able to generate yours from your library
    to_draw = np.random.randint(0, 255, (height, width))
    img = plt.imshow(to_draw)
    # you can convert the graph to arrays and save to memory
    imgIO = StringIO()
    img.write_png(imgIO, noscale=True) # save to memory
    imgIO.seek(0)
    # and send that image as file as static file of url
    # like... /plot/?width=100&height=100
    return send_file(imgIO, mimetype='image/png')

# this is the main page with the form and user input
@app.route('/', methods=['GET', 'POST'])
def index():
    # set the default values
    height, width = 100, 100
    # handle whenever user make a form POST (click the Plot button)
    if request.method == 'POST':
        try:
            # use this to get the values of user input from the form
            height = int(request.form['height'])
            width = int(request.form['width'])
        except ValueError:
            pass
    # and pass the context back to the template
    # if no form is POST, default values will be sent to template        
    return render_template('index.html', height=height, width=width)


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

And the template at templates/index.html:

<html>
  <head>
    <title>Micro Plot!</title>
  </head>
  <body>
  <h1>Interactive Plot</h1>
  <form action="/" name="plot" method="POST">
      <p><input type="text" name='height' value="{{ height }}" /></p>
      <p><input type="text" name='width' value="{{ width }}" /></p>
      <p><input type="submit" value="Plot Now!"></p>
  </form>
  <img src="{{ url_for('plot', height=height, width=width) }}" />
  </body>
</html>

The trick is to set the image src to send a GET request to the url, and then Flask's /plot/ view to render an in-memory image and feed back as static.

Key Notes:

The url_for will then dynamically generate the src as like /plot/?width=xxx&height=xxx.

To get the querystring from the url in the view, use request.args.get('KeyName').

Once your plot is ready, save it in the memory with Python StringIO module and use Flask's send_file to serve as static content.

You should read and learn more about Flask and HTML, you cannot build something really amazing without having a good understanding of how these things work together.

I hope this helps you understand the underlying techniques, and Good Luck!


Solution 2:

I ended up creating my own answer with the help of elyase, and the code was pulled into an example folder in the bokeh project. Check it out here:

https://github.com/bokeh/bokeh/tree/master/examples/embed/simple


Post a Comment for "Embedding An Html Page Inside Flask"