Flask static_folder hosted on S3 Flask static_folder hosted on S3 flask flask

Flask static_folder hosted on S3


I recently developed a Flask extension to deal with just this situation. It's called Flask-S3, and you can read the documentation for it here.

As an example, here is how you would integrate it into your Flask application:

from flask import Flaskfrom flask_s3 import FlaskS3app = Flask(__name__)app.config['S3_BUCKET_NAME'] = 'mybucketname's3 = FlaskS3(app)

You can use the extension to upload your assets to your chosen bucket:

>>> from my_application import app>>> from flask_s3 import create_all>>> create_all(app)

Flask-S3 is blueprint aware, and will upload all assets associated with any registered blueprints.


I wish the flask.Flask constructor's static_url_path argument would accept a full URI, but it screams about the path needing a leading slash when you try that. If it accepted it, you could just use url_for after setting static_url_path='http://my_s3_bucket.aws.amazon.com/' or so.

Another possible solution is to use a context processor. I believe this is the cleanest solution, but I don't have much experience with flask. It sure looks clean. Using a context processor, I pull the URL from the environment (I'm using heroku so it's wicked easy to set). Then the context processor makes the static_url variable available in my templates.

In app.py:

# Environment has STATIC_URL='http://my_s3_bucket.aws.amazon.com/'@app.context_processordef inject_static_url():    """    Inject the variable 'static_url' into the templates. Grab it from    the environment variable STATIC_URL, or use the default.    Template variable will always have a trailing slash.    """    static_url = os.environ.get('STATIC_URL', app.static_url_path)    if not static_url.endswith('/'):        static_url += '/'    return dict(        static_url=static_url    )

In the template:

<link rel="stylesheet" type="text/css" href="{{ static_url }}css/main.css" />

The result

<link rel="stylesheet" type="text/css" href="http://my_s3_bucket.aws.amazon.com/css/main.css" />


I know this is an old question but here's how I get around this issue.

  • Import Flask's url_for method under a different name (e.g., flask_url_for)
  • Create your own custom url_for method, which calls flask_url_for and then uses string replacement to add in your S3 bucket url.

I like this strategy because it's simple and intuitive to use, and the interface is exactly like the original url_for method.

from flask import url_for as flask_url_forfrom flask import current_appPRODUCTION_URL = 'https://s3.amazonaws.com/MY-BUCKET-NAME'def url_for(path, **kwargs):    url = flask_url_for(path, **kwargs)    if url.startswith("/static") and not current_app.debug:        url = url.replace("/static", "", 1)        return PRODUCTION_URL + url    return url