Serving Static Files with Flask

python_tutorials

Setting Up Flask

Flask is a great choice for building web applications in a modular way using Python. Unlike Django and other analogues like Ruby on Rails, Flask is a micro-framework. This means it includes only what is necessary to do core web development, leaving the bulk of choices beyond that minimal subset to you.

This approach has a huge advantage in keeping your code and workflow simple, particularly on smaller projects. Here we will show you how to serve static files such as JS, CSS, and images using Flask.

Make sure you have Python 3 installed. You can use pyenv for this, which helps you select Python versions. Follow this guide to set up Python 3 using pyenv. If you prefer virtualenv instead, be sure to check out the documentation, but just make sure you have a Python 3 environment active.

Before we can start serving static files with Flask, we need to install it and get a simple app going. To do this, install Flask using the command:

$ pip install flask

Now we’ll create a basic Flask app that serves a landing page on which we will display the classic text, “Hello World”.

$ mkdir serving_static

In this new directory, create a new file which creates the Flask application and runs it. In this file, we create a Flask route where we will display a welcome message using a Flask template.

# serve.py

from flask import Flask
from flask import render_template

# creates a Flask application, named app
app = Flask(__name__)

# a route where we will display a welcome message via an HTML template
@app.route("/")
def hello():
    message = "Hello, World"
    return render_template('index.html', message=message)

# run the application
if __name__ == "__main__":
    app.run(debug=True)

Now let’s create the template to display our message. Create an HTML file in the location “serving_static/templates/index.html” with the following HTML code. Note the message Python variable passed in from the serve.py file above.



  
    Flask Shop
  
  
    

{{message}}

We are now ready to run the application. Back in the “serving_static” root directory, run the application using the command:

$ python serve.py

If the server started up correctly, you will get a message that it started and a URL to view the application. Open up this URL in your browser, and you should now see our “Hello, World” message displayed in the browser.

Hello World

Flask creates application routes using decorators such as the one seen in serve.py above. A decorator such as @app.route("/") creates a new route at the provided path. The function definition below it contains the application logic that will run when a request is received at that URL.

Serving Static Files Using a Static Directory

The most common static files you will want to serve in a web application are your application’s CSS files for styling the application, as well as JavaScript files that add dynamic behavior to the page. In this section we will see how to serve both CSS and JavaScript files by adding them to the simple application we created above.

Static files in Flask have a special route. All application URLs that begin with “/static”, by convention, are served from a folder located at “/static” inside your application’s root folder.

This means if we create a “/static” folder inside our main “serving_static” folder, we will be able to serve static files such as CSS, JS, images, and other assets by simply placing them inside that “/static” folder.

Now let’s change the welcome message in our application’s index page to introduce “The Flask Shop”, a fictional shop where visitors can buy Flask books.

First, we want the index page template to show the visitor the name of the shop, as well as a list of books that are on sale. Update your HTML template at “serving_static_/templates/index.html” with these changes to look as follows.



  
    Flask Shop
    
  
  
    

{{message}}

On sale this week alone:

  1. Flask By Example
  2. Uncluttered Flask
  3. Flask From First Principles

You will notice that the title of the page is now “Flask Shop”, and we have included a list of Flask books for sale. The visitor should be able to see on the page this list of books when they visit the home page of our shop application.

Take a look at the head section of the HTML template again. You will notice that now we are linking to a new file, specifically a CSS stylesheet named “style.css”. The path, “/static/style.css” shows that this file is located in our “/static” folder.

Remember that Flask serves files placed in “/static” automatically as static files, instead of trying to run these files as Python source files.

Let us now create a static folder at “serving_static/static” to contain all our static files.

Inside this static folder, let’s create the new file “style.css”, and add the following CSS rules to add some style to our shop front application.

/* static/style.css */

h1 {
    color: navajowhite;
    font-variant-caps: all-small-caps;
    font-size: 46px;
}

h3 {
  color: white;
  font-size: 36px;
}

li {
  color: red;
  font-size: 50px;
}

body {
    background: firebrick;
}

With these style rules defined, our application will shed the plain white background we saw in our “Hello, World” example for a more colorful “firebrick” red background. We are also defining distinctive white styling for the text on the page.

Now let us actually update the message we are displaying on the page. Go back into “serving_static/serve.py” and update the message variable to be the name of the shop. Find the hello() function and update the message variable as follows:

# serve.py

...

# a route where we will display a welcome message via an HTML template
@app.route("/")
def hello():
    message = "The Flask Shop"
    return render_template('index.html', message=message)

...    

Now, restart your server, and run python serve.py again. Then visit the application URL at localhost:5000 and you should see our list of Flask books.

The Flask Shop

Notice that the style of the application is now being picked up from our CSS file which is being served from the “/static” directory by our Flask app.

If you look again at our “serving_static/templates/index.html” template, before the closing tag, we are inserting a JavaScript script tag.

The URL of this script is “/static/scripts.js”. This is another static file that will be served by Flask from our “/static” folder.

Let us now create this JavaScript file at “serving_static/static/scripts.js”. The contents will be some JavaScript code to dynamically change the background color of our shop application every second. This creates a dramatic effect to draw attention to the limited time sale in our fictional Flask shop.

// scripts.js

// a couple of different backgrounds to style the shop
var background1 = 'black';
var background2 = 'firebrick';

// this lets us toggle the background state
var color = true;

// every 1 second, switch the background color, alternating between the two styles
setInterval(function () {
  document.body.style.backgroundColor = (color ? background1 : background2)
  color = !color;
}, 1000);

Now, stop your server and re-run python serve.py once again. When you visit our application in the browser, the page background should flash and change every 1 second from a shade of red, this:

Red background

to a shade of black, like this:

Black background

The setInterval function in our JavaScript code changes the background every second in a continuous time loop.

We are now serving JavaScript and CSS files from our “/static” folder to style and enhance the behavior of our application.

If you have additional CSS or JavaScript files, you can add them to the “/static” folder in the same way and reference them as we have done above.

Serving JavaScript Files

Another common use case when it comes to serving static files in web apps is serving third party libraries such as Backbone.js, Vue.js, Bootstrap or React.

Any kind of library you want to include can be served in almost the same way that we saw above from our “/static” directory.

As an example, let us see how to include the Backbone.js JavaScript library in our application.

A good idea when serving third party libraries is to locate them inside a special lib or vendor directory inside the “/static” folder. You can name this third-party folder whatever you like.

The key, however, is to put external libraries in their own folder where you can easily upgrade versions or do other management separate from your own application code.

With this in mind, create a new folder at “serving_static/static/lib”. Since we are including Backbone.js, download the single-file version of Backbone.js here, and then place it inside the new lib folder inside of our “/static” folder.

Backbone.js has a hard dependency on Underscore.js, another JavaScript library, which provides many essential utilities. So download the latest version of Underscore.js here and place it next to Backbone.js in your “/static/lib” folder.

Now we can make use of Backbone.js by including it in our page template and calling its functions.

Back in your template, in the file “serving_static/templates/index.html”, find the

closing tag. After it, on a new line, create a new heading element which we will manipulate with Backbone.js.

In addition, add new script tags before the closing tag. In these tags, we include Underscore.js and Backbone.js, as well as write some code to update the DOM using Backbone code.

The updated part of the index.html template should look as follows.



...
  1. Flask By Example
  2. Uncluttered Flask
  3. Flask From First Principles

Backbone

...

Our last