Skip to content

Template for websites built using Django and deployed on Heroku and AWS S3.

License

Notifications You must be signed in to change notification settings

yl8976/django-heroku-s3-template

Repository files navigation

Django Heroku S3 Template

Template for websites built using Django and deployed on Heroku and AWS S3. This solution is great because Heroku has a perpetual free tier (albeit with numerous limitations) and AWS S3 is also free up to 5GB (but only for the first year), meaning you can deploy your entire Django project at virtually zero cost.

AWS S3 is necessary for handling user uploads and adding static files because Heroku has an emphemeral file system. This template project uses PostgreSQL as its database as it is highly scalable and integrates with Heroku very easily (and for free!).

Requirements

  • Django (2.2.4)
  • Python (3.7.3)
  • PostgreSQL (11)

Setup

Clone the Template

Option 1: Using GitHub's Templating Feature

Press the "Use this template" button at the top of this repository. Follow the steps to name and create your own copy of this repo!

Option 2: Manually Clone

First, navigate to the folder you want your project to live on your command line interface (cmd.exe on Windows, Terminal on macOS). Then, type:

git clone https://github.com/younglee327/django-heroku-s3-template.git

Rename the Django Project

Source

If you would like to rename your Django project after you've created it (I often end up doing this because I want to name my app the project name, not the project itself), this is the way to do it. Your current Django project structure should look like this:

django-heroku-s3-template
├── Procfile
├── README.md
├── manage.py
├── myapp
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py
│   ├── models.py
│   ├── templates
│   │   └── myapp
│   │       ├── base.html
│   │       ├── home.html
│   │       └── model_form_upload.html
│   ├── tests.py
│   └── views.py
├── myproject
│   ├── __init__.py
│   ├── settings.py
│   ├── storage_backends.py
│   ├── urls.py
│   └── wsgi.py
├── requirements.txt
└── runtime.txt

Rename your project directory (myproject) and the following files inside your project directory into your own project name (the examples below use newprojectname as the new name):

# myproject/settings.py
ROOT_URLCONF = 'newprojectname.urls'
WSGI_APPLICATION = 'newprojectname.wsgi.application'
# myproject/wsgi.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'newprojectname.settings')
# manage.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'newprojectname.settings')
# Procfile
web: gunicorn newprojectname.wsgi --log-file -

Lastly, rename the root folder django-heroku-s3-template to whatever you want to call your project. It's common to just name it the same name as your project, although it does not affect your Django app in any way.

Rename the Django App

This template also comes with a barebones Django app called myapp. It contains some templates for uploading files, a model describing a Django form, and views that handle the appropriate requests. Rename these to an appropriate app name in the following files (the examples below use newappname as the new name):

# myproject/urls.py
"""newappname URL Configuration
# myproject/urls.py
from newappname import views
# myproject/settings.py
INSTALLED_APPS = [
    'newappname.apps.NewappnameConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'storages',
]
# myproject/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'newappname_db',
        'USER': 'newappnameuser',
        'PASSWORD': os.getenv('DB_PASSWORD'),
        'HOST': 'localhost',
        'PORT': '',
    }
}
# myapp/views.py
return render(request, 'newappname/home.html', { 'documents': documents })
# myapp/views.py
return render(request, 'newappname/model_form_upload.html', {
        'form': form
    })
# myapp/apps.py
class NewappnameConfig(AppConfig):
    name = 'newappname'
<!-- myapp/templates/myapp/home.html -->
{% extends 'newappname/base.html' %}
<!-- myapp/templates/myapp/model_form_upload.html -->
{% extends 'newappname/base.html' %}

Don't forget to rename the folders myapp and myapp/templates/myapp as well!

Installing Dependencies

In the command line, navigate to the project's root folder and run

python3 -m venv env

This will create a virtual environment called env (using Python 3's native virtual environment module, venv) where we can install our dependencies separately from other Python projects. Now run

source env/bin/activate
pip install -r requirements.txt

to install our dependencies.

Using python-dotenv for Local Development

This package allows you to load variables into our Django project as environment variables so that it will stay out of source control. This is particularly important for Django projects in two places: the SECRET_KEY in settings.py, our AWS keys, and our database's password, also stored in settings.py.

The way it works is simple: we just create a file .env within our project (which will store our sensitive data), and now we'll be able to import it anywhere within the project and load our environment variables. We just have to make sure not to add .env to source control! To begin, create an empty .env file in the same folder where our settings.py is using the touch command:

cd myproject # If you're not already in the folder
touch .env

To recap, our folder structure should now look like this (but your project and app will have been renamed):

django-heroku-s3-template
├── .env <- note this new file!
├── Procfile
├── README.md
├── manage.py
├── myapp
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py
│   ├── models.py
│   ├── templates
│   │   └── myapp
│   │       ├── base.html
│   │       ├── home.html
│   │       └── model_form_upload.html
│   ├── tests.py
│   └── views.py
├── myproject
│   ├── __init__.py
│   ├── settings.py
│   ├── storage_backends.py
│   ├── urls.py
│   └── wsgi.py
├── requirements.txt
└── runtime.txt

This template already has the following code added to the top of settings.py to load our .env file:

from dotenv import load_dotenv
load_dotenv()

At this point, parsed key-value pairs from the .env file is now present as system environment variables and they can be conveniently accessed via the method os.getenv(). Generate a SECRET_KEY value using this generator and copy the value of SECRET_KEY in settings.py and add it to .env like so, along with your PostgreSQL database password and AWS Keys:

SECRET_KEY=YOURSECRETKEY
DB_PASSWORD=YOURDBPASSWORD
AWS_ACCESS_KEY_ID=YOURAWSACCESSKEYID
AWS_SECRET_ACCESS_KEY=YOURAWSSECRETACCESSKEY
S3_BUCKET=NAMEOFYOURAWSS3BUCKET

Note how there are no spaces around the equal signs and there are no quotation marks for the variable values. When you deploy to Heroku, you'll define them in the Config Vars section in the project's Settings tab instead.

And that's it! Hopefully this template comes in handy for some people building Django apps like myself.

Additional Resources

About

Template for websites built using Django and deployed on Heroku and AWS S3.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published