Setting up the project
My aim when setting this up was to run the application locally using
DEBUG=True
, python manage.py runserver
, but to use Heroku for production.
Heroku
Heroku is pretty easy to use. I basically just followed the documentation for deploying a Djano app. Because I was using a slightly different configuration in my Django app, I had to do some shimmying at the heroku end.
To ensure that heroku runs the Django app using the staging.py
settings
module, you have to change the DJANGO_SETTINGS_MODULE
environment variable in
heroku:
|
|
It’s just as easy to set and unset environment variables in heroku
settings
in the same way:
|
|
You particularly don’t want your AWS settings going into settings.py
files,
hence the use of os.environ.get()
in base.py
You got to do this:
Settings
I experimented with the Two Scoops of Django convention of using separate settings files. This makes it easier to have versions of the application running locally and in production (or in “staging”). Thoroughly recommend that book by the way, although there are alternative ways to think about coding your business logic - such as Django Service Objects.
To achieve this, I set up the Django application in the normal way, but created
a new settings
folder in the “project folder” (which sits alongside the app
directory you should have set up as part of starting a new Django project), the
contents of which are as follows:
|
|
base.py
This contains most of the baseline settings already generated automatically by
django-admin startproject
. These settings are imported by the other “sub”
settings modules.
It looks like this (don’t copy and paste as there are placeholders in here):
|
|
staging.py
|
|
heroku_local.py
|
|
These are the settings used when running heroku local
(more on which
later). Here were are saying that everything that we need to run Heroku is
in the staging
settings module, but here we just want to override the
ALLOWED_HOSTS
setting.
.heroku_env
I use this to set environment variables for running heroku local web
with the
-e
flag:
|
|
Includes:
|
|
I also chuck my AWS keys here so I can test that locally. Kept out of the git repo, or course.
bash scripts to run everything
WRITE TEXT HERE.
amending the model
Amend model.py
and populate.py
accordingly. If using ModelSerialzer
you
don’t need to do too much more. Then you have to tear down the database (using
bash scripts/initialise.sh local
), ./manage.py makemigrations
, ./manage.py
migrate
, ,/manage.py populate
and finally ./manage.py createsuperuser
.
If you don’t want to do all that, then just run bash scripts/initialise.sh
local --do_migrations
, then create the superuser.
manage.py commands to populate database
WRITE TEXT HERE.
Hosting Django static files in an AWS bucket
It took a lot of fannying around, but I finally go there. Here are the steps to doing it - hopefully this will enable a reproducable situation.
Create a new user on AWS
Here. Give it a decent simple username and ensure Programmatic Access is checked. Download the CSV containing the AWS Access ID and AWS Access Secret Key here before you navigate away.
Note of the ARN
By clicking on the newly created username at the above page. Copy and paste this and hang onto it because you’ll need this to set up your bucket policy.
Create a new bucket
Here. Give it a name and sensible region. Copy the settings from a previous one that works in Django if you can.
Set permissions
Set permissions by clicking on the bucket in the bucket list and going to Permissions tab, then Bucket Policy. I did a lot of fucking about here when I set this up for the first time but I found this the easiest way to start with a useable JSON file. Click the Policy generator button.
Create a policy
Using the policy generator. Select “S3 Bucket Policy” as Type. Select Allow,
paste your ARN from the user console into the Principle box, check All
Services, and then put the ARN for the bucket in the ARN box, using
arn:aws:s3::
Copy the resulting JSON file. You need to paste this into Bucket Policy text area and click Save. This should now mean that any application quoting this user’s id and secret key can programatically acess the files in the bucket. That’s the idea here.
Templates
When using the Django Rest Framework, you want to override the look and feel of the default site.
If you have set BASE_DIR
and TEMPLATES
in base.py
as follows:
|
|
then in your project root, create the following structure:
|
|
You can then customise these files to use a different CSS theme. As advised, I went to Bootswatch.
Don’t hard-code links in your
template now that
you’re using STATIC_ROOT
.
Pushing static files to AWS from heroku
When you git push heroku master
, heroku will automatically run python
manage.py collectstatic
and will put all static files into STATIC_ROOT
(which is set in staging.py
). The trick is to then push these to AWS so that
they become available to the links in your template files (via the STATIC_URL
variable set in staging.py
).
Use django-storages and configure it push to Amazon S3. This also requires boto3.