How to serve static files with Python 3 + Flask

Python Flask is a good microframework for building a minimal viable product to validate our ideas on the Internet. A modern web application encompasses documents that tell the web browser how to build the visuals of our web application and communicate with our server backend. Such documents are usually static in nature and are served as they are to the web browser without any processing from the server end.

Comparing setting up an instance of the Nginx server with adding code in our Flask application, the latter can be a more convenient way for us to realise our minimal viable product. This post documents the proof of concept that I did to serve static files with Python 3 and Flask.

Sample code to serve static files with Python 3 + Flask

The following is the code that I wrote to serve static files that are contained in a directory that is named as "static":

import os

from flask import Flask
from flask import send_from_directory

static_file_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static')
app = Flask(__name__)

@app.route('/dir', methods=['GET'])
def serve_dir_directory_index():
    return send_from_directory(static_file_dir, 'index.html')

@app.route('/dir/<path:path>', methods=['GET'])
def serve_file_in_dir(path):

    if not os.path.isfile(os.path.join(static_file_dir, path)):
        path = os.path.join(path, 'index.html')

    return send_from_directory(static_file_dir, path)'',port=8080)

For this code to work, I had placed it in the same directory level as the directory that is named as "static". The first 3 statements imported the os module, the flask.Flask class and flask.send_from_directory function from flask.

To get the directory that contains the static files, I first get the directory path of the Python file that contains this code by calling os.path.dirname(os.path.realpath(__file__)). I then call os.path.join to construct the path to the directory that contains the static files and store it in the static_file_dir variable.

I then create an instance of the Flask class for realising the web server and made it available via the app variable. With the app variable, I then decorated the serve_dir_directory_index function and the serve_file_in_dir function with app.route. That would cause Flask to direct HTTP GET requests for /dir to serve_dir_directory_index and HTTP GET requests for /dir/* to serve_file_in_dir.

Inside serve_dir_directory_index, I call send_from_directory to attempt to return a index.html that resides in the root level of static_file_dir. This would emulate the behaviour of returning a Webserver directory index for /dir.

Inside serve_file_in_dir, I first check whether the requested uri corresponds to an actual file. If not, it would mean that the HTTP GET request is directed at a directory within /dir. For such a case, I changed the path to point to a index.html that is located at the root level of that directory. Finally, I used send_from_directory to attempt to return the corresponding file back to the web browser.

The last statement,'',port=8080), starts the web server that listens on port 8080 for incoming HTTP requests.


About Clivant

Clivant a.k.a Chai Heng enjoys composing software and building systems to serve people. He owns and hopes that whatever he had written and built so far had benefited people.