Implementing Data#

Author: Mike Wood

Learning Objectives: By the end of this notebook, you should be able to:

  1. Implement local data onto a page using dynamically

  2. Write simple if statements using jinja

  3. Implement remote data from other pages dynamically

Local Data#

In this example, we will take a look at linking local data to a page. Specificaly, we’ll make a page to toggle through different images in a database. Let’s see an example script:

# import the Flask class from the flask module
from flask import Flask

# import the render_template function
from flask import render_template

# import the request function
from flask import request

# create a Flask object called app
app = Flask(__name__)

# define a route to the home page
# create a monthly_maps function
@app.route("/")
@app.route("/home")
def monthly_maps():
    return render_template('month_page.html', month='default')

# define a route to the person page
# add 'GET' to the methods
# create a month function
@app.route("/month", methods=['GET'])
def month():

    # retrieve the month from the requests
    month = request.args['month']

    # pass the month arg to the render template
    # for the month_page.html scriopt
    return render_template('month_page.html', month=month)

# add a main method to run the app
# as a typical Python script
if __name__ == '__main__':
    app.run()

In this example, we have created two “pages” yet both of them use the same month_page.html template.

<!doctype html>
<html>

<head>
<title>Month Map</title>
<meta name="description" content="A page to show a map for each month">

</head>

<body>
    <h2>Monthly Maps</h2>

    <!--Make a form with month action and get method-->
    <form action="/month" method="get">

        <!--Make a select feature to choose the months-->
        <select name="month" id="months">

            <!--Add an option on start-up for when months are not selected -->
            <!--Use jinja to implement a Python if statement-->
            {% if month=='default'%}
            <option value="default" selected disabled>Choose a month:</option>
            {% else %}
            <option selected>{{month}}</option>
            {% endif %}

            <!--Add options for each month-->
            <option value="Jan">Jan</option>
            <option value="Feb">Feb</option>
            <option value="Mar">Ma</option>
            <option value="Apr">Apr</option>
            <option value="May">May</option>
            <option value="Jun">Jun</option>
            <option value="Jul">Jul</option>
            <option value="Aug">Aug</option>
            <option value="Sep">Sep</option>
            <option value="Oct">Oct</option>
            <option value="Nov">Nov</option>
            <option value="Dec">Dec</option>
        </select>
        <input type="submit" value="Update">

    </form> <br>

    <!--Add an image for the month indicated by the month variable-->
    <!--Use jinja to implement a Python if statement-->
    {% if month!='default'%}
        <img src="static/{{month}}_map.png">
    {% endif %}
</body>

</html>

These files should yield the following pages: HERE

As we can see in this example, the value stored in the month variable is selected from the dropdown menu (i.e. the select feature), passed to the month page with the month() function, and then used to update the page with the {{month}} variable.

In this script, we also control the behavior of the home page using jinja, allowing us to write Python-like if statements. For example, when there has not yet been a month selected, we assign a default value to the dropdown but when it has been selected, we just use the selected month:

{% if month=='default'%}
<option value="default" selected disabled>Choose a month:</option>
{% else %}
<option selected>{{month}}</option>
{% endif %}

Similarly, when there has not yet been a month selected, we don’t display anything on the page yet:

{% if month!='default'%}
    <img src="static/{{month}}_map.png">
{% endif %}

Remote Data#

Just as we can add local data to our pages, we can also use data hosted on other pages. In this next example, we’ll see how we can make a page to display wave height data for California on the maps provided on the surf-forecast.com page HERE.

First, let’s have a look at the Python implementation:

# import the Flask class from the flask module
from flask import Flask

# import the render_template function
from flask import render_template

# import the request function
from flask import request

# create a Flask object called app
app = Flask(__name__)

# define a route to the home page
# create a wave_page function
@app.route("/")
@app.route("/forecast")
def wave_maps():
    return render_template('wave_page.html', hour=3)

# define a route to the forecast page
# create a forecast function
@app.route("/forecast", methods=['POST'])
def forecast():

    # retrieve the hour from the request form
    hour = int(list(request.form.keys())[0])

    # retrieve the action string from the request form
    add_string = list(request.form.values())[0]
    
    # make an if statement to increment the hour by 3
    # depending on which button was pressed
    if add_string=="<<":
        if hour>3:
            hour -= 3
    elif add_string==">>":
        if hour < 300:
            hour += 3

    # pass the hour arg to the render template
    # for the wave_page.html page
    return render_template('wave_page.html', hour=hour)

# add a main method to run the app as a typical Python script
if __name__ == '__main__':
    app.run()

The accompanying html template for this page is provide here:

<!doctype html>
<html>

<head>
<title>Wave Forecast</title>
<meta name="description" content="A page to show a map for each month">

</head>

<body>
    <!--Add a header for the map page-->
    <h2>Wave Forecast</h2>

    <!--Make a form with forecast action and get method-->
    <form action="/forecast" method="post">

        <!--Add a << button to go back 3 hours-->
        <input type="submit" name="{{hour}}" value="<<">
        
         <!--Add a to display the hour-->
         <label value="{{hour}}">{{hour}}</label>
        
         <!--Add a >> button to go forward 3 hours-->
         <input type="submit" name="{{hour}}" value=">>">

    </form> <br>

    <!--Add an image for the month indicated by the month variable-->
    <img src="https://assets.weather-forecast.com/maps/dynamic/California.htsgw.imperial.{{hour}}.cc23.jpg"><br>
    <img src="https://www.surf-forecast.com/assets/scales/htsgwscale.imperial-ddef88291e71ae07346499307394465dfa90235d0b3db3e94f1929c5cbcebeea.gif">
</body>

</html>

Checkout an example of what this page should look like HERE

In this example, we are again providing our user a way to update the page dynamically, although this time we use a POST request rather than a GET request. In this example, we use the key of the form dictionary (the hour in this case) to pass the hour variable and the value to identify which button was pressed (<< or >>). When the hour is retrieved, is it incremented, if possible using the forecast function. The updated hour is then passed back to the page.

On the page itself, the hour variable is used to update the map requested in the following line:

<img src="https://assets.weather-forecast.com/maps/dynamic/California.htsgw.imperial.{{hour}}.cc23.jpg">