deploying a django app to heroku with easy static files on s3
git clone email@example.com:eknuth/django-heroku-s3-bootstrap-demo.git
Django on HerokuHeroku used to be limited to ruby apps, but it has recently become much more flexible with the addition of the cedar stack. Now it supports python 2.7 and uses pip to install modules from a standard requirements.txt file. They have also started offering a free 5mb postgresql db to go along with their current freemium offering, which is fantastic. That doesn't sound like a lot of space, but you'd be surprised how much information you can cram into 5 mb.
Initial SetupYou can follow the django instructions from heroku here: http://devcenter.heroku.com/articles/django If you are using macosx, or virtualenv uses python 2.6 by default, I would suggest specifying 2.7 when you create the environment. Heroku is using 2.7 and will complain about pip installing importlib which was not included by default in python 2.6.
virtualenv --no-site-packages . -p /usr/local/bin/python2.7Open the site on heroku using the "heroku open" command and verify that you get the django welcome screen. You should have no urls configured.
Admin and Static FilesYou should now have a working empty project. Let's turn on the django admin app and fire up the development server. As a side note, this config will import settings from settings_local.py, if it exists and overwrite the ones in settings.py. This local settings file is not committed to the repo and won't get deployed to heroku. Follow the instructions to install the django admin app and then run manage.py syncdb and then runserver. If everything went ok, you should be able to log in to your admin console. Now, commit and push your app to heroku. Run the manage.py commands on heroku and magically your admin console is live on the web.
@render_toNow let's create a view and wire up that template to a url. Now is the time to add on a django project that will make things easier for us. I really love the render_to decorator from django-annoying. Run "pip install django-annoying", and it will be ready to go. Don't forget to save your updated requirements with a "pip freeze >requirements.txt".
relative pathsAdd the template dir and a little snippet of python to use relative paths. This will make life easier in the future. In the urls.py file, uncomment the following home view: url(r'^$', 'om.views.home', name='home'), And create a views.py file to grab the template and render it. Now when you open the app on your development server, you get an actual "hello world" page. Unfortunately we are missing the css file, so it is unstyled. In your root project, create a static folder and inside that create another folder named css. Copy bootstrap.css into static/css. To reference this css file, edit hero.html and change the line with bootstrap.css to this:
<link href="css/bootstrap.css" rel="stylesheet">In order to make the STATIC_URL template tag work, we need to update STATICFILES_DIRS in settings.py to:
STATICFILES_DIRS = ( os.path.join(SITE_ROOT, 'static'),)We also need add some template context processors with this:
TEMPLATE_CONTEXT_PROCESSORS = ( 'django.contrib.messages.context_processors.messages', 'django.contrib.auth.context_processors.auth', 'django.core.context_processors.static', )When we open the page served from our development server, we are good to go. The page is styled and looks awesome.
Enter S3Amazon provides an excellent service for doing just that. Amazon's web services and the simple storage system are cheap and easy to use. There is also an excellent module for using s3 with django's static files app and the collectstatic management command with s3 as a backend. django-storages makes it incredibly simple to use s3 for our static files.
django-storages and botoFirst we want to install the module with "pip install django-storages" and add 'storages' to your INSTALLED_APPS tuple and set your storage type with:
STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'We will also need to install boto, the python module for dealing with s3. Use "pip install boto" for that. Log in to the amazon web services management console and create a new bucket. Add the name of the bucket and your access keys to settings.py like this:
AWS_ACCESS_KEY_ID = 'ACCESS KEY' AWS_SECRET_ACCESS_KEY = 'SECRET' AWS_STORAGE_BUCKET_NAME = 'django-blog
set up the s3 bucketLook at the bucket properties and grab the url for the bucket. Update your STATIC_URL setting to point to the bucket. In this case it will look like this:
STATIC_URL = 'https://s3.amazonaws.com/django-blog/'
deploymentNow run manage.py collectstatic and you will see all the files being copied to your bucket. Freeze your requirements file and commit your repo. Now when you push to heroku, you should see your website with the bootstrap.css file pulled from s3.