Flask web server

Install the Flask library to host web-based projects run by Python.

Basic template

from flask import Flask, render_template, request, redirect, send_file

app = Flask(__name__)
app.config['SECRET_KEY'] = 'code used to secure cookies from tampering'

# Return templates/index.html
@app.route("/")
def index_page():
    return render_template("index.html")

# Return a binary file
@app.route('/promovideo')
def promovideo():
    return send_file("promovideo.mp4")

# Use the URL path to supply a parameter
@app.route('/user/<userid>')
def users(userid):
    return "User page for "+userid

# Get values from a HTML form
@app.route("/page2", methods=['GET','POST'])
def page2():
    # HTML with <input name='person'> will create a request.values['person']
    # .values contains .args and .form combined
    form = dict(request.values) # Convert all values into a dictionary
    person = form['person']
    return f"Hello, {person}, welcome to my website"

# Start the web server. These should be the last lines.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=80, debug=True)

Upload a file from webpage to flask

HTML extract

  • Note that enctype=”multipart/form-data” is mandatory for uploading binary files
<!DOCTYPE html>
<html>
  <body>
    <form action=“http://localhost/upload" method="POST" enctype="multipart/form-data">
      <input type="text" name="person">
      <input type="file" name="my_upload">
      <input type="submit" name="submit" value="Answer">
    </form>
  </body>
</html>

Corresponding Python/Flask code

  • secure_filename() protects from security risks with a user-supplied filename
# from werkzeug.utils import secure_filename
# import os
# app.config['MAX_CONTENT_LENGTH'] = 1<<24 # 16MB

@app.route("/upload", methods=["POST"])
def upload_photo():
    f = request.files['my_upload']  # refer to the HTML <input> name attribute
    f.save(os.path.join(app.root_path, 'photos', secure_filename(f.filename)))
    return 'file uploaded successfully'

Send / receive JSON data

@app.route("/api", methods=['GET','POST'])
def api():
    if request.is_json:
        data = request.json # list/dictionary of values
        print(data)
        result = {"status": "received"}
    else:
        result = {"status": "error"}
    return jsonify(result)

Jinga2 templates

Jinga2 is a templating language you can use to generate HTML documents from your Python data.

An example of a Jinga2 HTML document, illustrating the most common constructs


<!DOCTYPE html>
<html>
    <body>
        <!-- Insert content of variable -->
        <h1>Welcome, {{ personName }}!</h1>

        <!-- if statement -->
        {% if personName != "" %}
            <!-- Insert content of variable -->
            <h1>Welcome, {{ personName }}!</h1>
        {% else %}
            <h1>Welcome visitor!</h1>
        {% endif %}

        <!-- for loop -->
        <ul>
        {% for name in people %}
            <li>{{ name }}</li>
        {% endfor %}
        </ul>

        <!-- if variable is defined -->
        {% if variable is defined %}
            <p>variable is defined with value {{ variable }}</p>
        {% endif %}

        <!-- if variable is empty -->
        {% if variable|length %}
            <p>variable is not empty</p>
        {% else %}
            <p>variable is empty</p>
        {% endif %}

        <!-- drop down list: default to the option based on value of `choice` -->
        <select name="day">
            <option {{ "selected" if choice=='Monday' else "" }}>Monday</option>
            <option {{ "selected" if choice=='Tuesday' else "" }}>Tuesday</option>
        </select>

    </body>
</html>

To render this from Flask

  • Place the template HTML file into a templates/ folder for Flask to find it.
  • Pass all the Python data you want Jinga2 to have access to via the render_template() function.
return render_template("main.html", personName=p, people=names, variable=v)

Minimalist example

Python file

from flask import Flask, render_template, request, send_file
import random

app = Flask(__name__) # Create the server object variable
app.config['SECRET_KEY'] = str(random.randint(0,100000000))

@app.route("/")
def main_page():
    return send_file("main.html")

@app.route("/process", methods=['POST'])
def form_process():
    received = dict(request.values)
    text1 = received['text1'] # Dictionary key is the 'name' attribute in HTML
    # Do whatever processing you want with the data
    print("The user sent",text1)
    # Send a response
    return render_template("response.html", info=text1)

if __name__ == "__main__":
    # Start Flask webserver
    app.run(host="0.0.0.0", port=80, debug=True)

main.html

<!DOCTYPE html>
<html>
    <head><title>Flask demo</title></head>
    <body>
        <h1>Welcome to my demo project</h1>
        <form method="POST" action="/process" enctype="multipart/form-data">
            <p>What do you want to send to the server?</p>
            <input type="text" name="text1" value="">
            <input type="submit" name="submit" value="Send">
        </form>
    </body>
</html>

templates/response.html


<!DOCTYPE html>
<html>
    <head><title>Flask demo</title></head>
    <body>
        <h1>Thank you for your submission</h1>
        <p>You sent: {{ info }}</p>
        <a href="/">Return to main</a>        
    </body>
</html>


Copyright © Paul Baumgarten.