Utilizing S3 for a Heroku Django App

January 02, 2012

With the help of a few articles, I was able to use Amazon’s S3 service to host static files for a Django app hosted on Heroku. Below are the steps I followed to get this working.

Before you start, make sure your virtual environment is activated.

    $ source venv/bin/activate
    

1. The central library we’ll be using is django-storages, a library for using various storage engines with Django. Documentation here.

    $ pip install django-storages
    

2. You’ll also need boto, a dependency for django-storages. Boto is a Python library for interfacing with Amazon Web Services.

    $ pip install boto
    

3. In your settings.py, add 'storages' to your list of INSTALLED_APPS.

4. Add the following line to your settings.py:

    STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
    

This allows django-admin.py collectstatic to upload your static files to your S3 bucket.

5. Add Amazon Web Service parameters to settings.py. Keep in mind that if you are using a public repo on github, all of these parameters are exposed. Also, boto doesn’t like a bucket name with capital letters, so make sure you are using a bucket with an all lower-case name.

    AWS_ACCESS_KEY_ID = 'XXXXXXXXXXXXXXXXXXX'
    AWS_SECRET_ACCESS_KEY = 'xxXXXxxXxxXxXXXxxXxXxxXXXXxxXxX'
    AWS_STORAGE_BUCKET_NAME = 'bucket name'
    

6. In settings.py change your STATIC_URL to point to your S3 URL.

    STATIC_URL = 'https://s3.amazonaws.com/bucket-name/'
    

If you are using the built-in Django admin app, also update ADMIN_MEDIA_PREFIX:

    ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'
    

7. Run manage.py collectstatic. This should copy your static files to your S3 bucket.

8. Check your app locally. Your static files should now be served from S3. Once you verify that is everything is working, update your app requirements:

    $ pip freeze > requirements.txt
    

9. If you don’t have one already, create a .slugignore file in the root of your repo. This file is simliar to a .gitignore file, except files and folders are still tracked in the repo but are not compiled as part of your app on Heroku. Add the following line to the .slugignore file to ignore the static directory:

    static
    

Now your static files are being served from S3 and your Heroku slug size is smaller; which, according to Heroku, allows for better app performance.