How to serve static files in Flask

Solution 1:

The preferred method is to use NGINX or another web server to serve static files; they'll be able to do it more efficiently than Flask.

However, you can use send_from_directory to send files from a directory, which can be pretty convenient in some situations:

from flask import Flask, request, send_from_directory

# set the project root directory as the static folder, you can set others.
app = Flask(__name__, static_url_path='')

@app.route('/js/<path:path>')
def send_js(path):
    return send_from_directory('js', path)

if __name__ == "__main__":
    app.run()

Alternatively, you could use app.send_file or app.send_static_file, but this is highly discouraged as it can lead to security risks with user-supplied paths; send_from_directory was designed to control those risks.

Solution 2:

If you just want to move the location of your static files, then the simplest method is to declare the paths in the constructor. In the example below, I have moved my templates and static files into a sub-folder called web.

app = Flask(__name__,
            static_url_path='', 
            static_folder='web/static',
            template_folder='web/templates')
  • static_url_path='' removes any preceding path from the URL (i.e. the default /static).
  • static_folder='web/static' to serve any files found in the folder web/static as static files.
  • template_folder='web/templates' similarly, this changes the templates folder.

Using this method, the following URL will return a CSS file:

<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">

And finally, here's a snap of the folder structure, where flask_server.py is the Flask instance:

Nested Static Flask Folders

Solution 3:

You can also, and this is my favorite, set a folder as static path so that the files inside are reachable for everyone.

app = Flask(__name__, static_url_path='/static')

With that set you can use the standard HTML:

<link rel="stylesheet" type="text/css" href="/static/style.css">

Solution 4:

I'm sure you'll find what you need there: http://flask.pocoo.org/docs/quickstart/#static-files

Basically you just need a "static" folder at the root of your package, and then you can use url_for('static', filename='foo.bar') or directly link to your files with http://example.com/static/foo.bar.

EDIT: As suggested in the comments you could directly use the '/static/foo.bar' URL path BUT url_for() overhead (performance wise) is quite low, and using it means that you'll be able to easily customise the behaviour afterwards (change the folder, change the URL path, move your static files to S3, etc).

Solution 5:

You can use this function :

send_static_file(filename)
Function used internally to send static files from the static folder to the browser.

app = Flask(__name__)
@app.route('/<path:path>')
def static_file(path):
    return app.send_static_file(path)