Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask static_folder hosted on S3

I am trying to reroute all of my /static content to host on Amazon S3. My first thought was to use global config['path'] throughout my jinja templates, but this won't work for external css and js files, plus it is kind of messy. I found the static_folder and static_url_path released in 0.7 and this seems like what I want. However, when I go to http://localhost:8000/static/img/abc.jpg it does not locate the files on S3. Am I using this feature right or is there some other way to do this?

Thanks!

like image 591
Tim Avatar asked Feb 25 '12 04:02

Tim


People also ask

Where are static files stored in Flask?

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.

What kind of website can be hosted on S3?

You can use Amazon S3 to host a static website. On a static website, individual webpages include static content. They might also contain client-side scripts. By contrast, a dynamic website relies on server-side processing, including server-side scripts, such as PHP, JSP, or ASP.NET.

How do I access static files in Flask?

Flask – Static Files Usually, the web server is configured to serve them for you, but during the development, these files are served from static folder in your package or next to your module and it will be available at /static on the application. A special endpoint 'static' is used to generate URL for static files.


2 Answers

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 Flask
from flask_s3 import FlaskS3

app = 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.

like image 174
Edwardr Avatar answered Sep 27 '22 18:09

Edwardr


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_processor
def 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" />
like image 34
Colin Dunklau Avatar answered Sep 27 '22 19:09

Colin Dunklau