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 callsflask_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