Part 3: Creating a Django project using Amazon Web Services for Heroku in Termux on Android

In the first part of our series we installed Termux to develop apps in Python on Android as well as Heroku CLI to deploy those apps on the cloud application platform. The second part was about using common developing tools such as Virtualenv and Git in such a manner that it would be convenient and easy to commit and push changes from our local app to Heroku.

In this part we will finally get to create our first Django web application and get Django to use Amazon Web Services (AWS) to serve static files (JavaScript, CSS, …). AWS is free to a certain limit, but it will be enough to run and test our app without spending a penny. All of this can be done either in Termux or under a common Linux distribution.

First of all, installing Django:


pip install django

Change directory to the name_of_app:

cd name_of_app

Run the following command to start a Django project and create the directory tree necessary:

django-admin startproject name_of_app

Installing postgres and psycopg2 is more complicated (in antoher Linux system, there is no need for the “make clang” option written below):

apt-get install postgresql
apt-get install postgresql-dev python-dev make clang
pip install psycopg2
pip install psycopg2-binary

In the Heroku dashboard, under Resources -> Add-ons search and install Heroku Postgres.
Or in the command line after login with Heroku:

heroku addons:create heroku-postgresql:hobby-dev

The database URL should automatically be added to your app’s config vars on Heroku. If not, follow the steps below:
Get the database URL using:

heroku pg:credentials:url

Copy the URL under connection URL to your Heroku app, in the dashboard under settings -> Config Vars. In the KEY field add DATABASE_URL and the VALUE field add the database URL copied.
Or use the Heroku Command Line Interface with:

heroku config:set DATABASE_URL=copied_database_url

Install the following to get Heroku to setup the project.
decouple is used to configure the settings file so not to display variables in directly in the file but in a .env file not committed by git.
dj-database-url, Django database configuration from environment variable.

pip install python-decouple
pip install dj-database-url

We’ll then use Gunicorn to process requests to the Django server, and put all necessary Python packages in the requirements file.

pip install gunicorncd name_of_project/
pip freeze > requirements.txt

First copy the secret key inside name_of_project/name_of_project/settings.py and enter it in your heroku dashboard under settings -> Config Vars. In the KEY field type SECRET_KEY and in VALUE the secret key chain of characters. The ALLOWED_HOSTS key will get the value name_of_app.herokuapp.com. For the first deployment and to ensure everything runs smoothly we’ll add a DEBUG with value True.
Or use the Heroku CLI:

heroku config:set SECRET_KEY=secret_key_chain
heroku config:set DEBUG=True
heroku config:set ALLOWED_HOSTS=name_of_app.herokuapp.com

Then edit name_of_project/name_of_project/settings.py:
Secret key and debug will be taken care of by decouple
In allowed hosts, put your app address (a Heroku extension or domain name)
The database address will be specified by dj_database_url and decouple
The last few lines are about static files, to create the folders if non-existent and where to find them.

from decouple import config
import dj_database_url
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config(‘SECRET_KEY’)
# SECURITY WARNING: don’t run with debug turned on in production!
DEBUG = config(‘DEBUG’, default=False, cast=bool)
ALLOWED_HOSTS = [‘name_of_app.herokuapp.com’]# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = { ‘default’: dj_database_url.config( default=config(‘DATABASE_URL’) ) }

Create a file that will tell Heroku worker to run Gunicorn at name_of_project/Procfile:

If you want to run the web application locally, you will need to create a .env in your application folder where you will store your config variables and values. You will need to create a local database as such:

su - postgrescreateuser name_of_db_user
createdb name_of_db --owner name_of_db_user
psql -c "ALTER USER name_of_db_user WITH PASSWORD 'the_password'"
exit

Then create the .env file:

Now onto using Amazon Web ServicesS3 to serve our app’s static files.

Create an account on AWS.

When done, on your account home page search for IAM in “Find Services”. We will use this service to create a group using the right policies for our app, and a user attached to that group whose crendentials will be used in our app.

Image for post
Image for post

Once in the IAM’s dashboard, click on “Groups” then “Create New Group”. Enter your group’s name, click on “Next Step”.

Under “Attach Policy”, check the “AmazonS3FullAccess” box. Click on “Next Step” and then “Create Group”.

Go to “Groups”, click on the group you created and then on the “Permissions” tab. After you clicked on “Create Group Policy”, check the “Policy Generator” tab then “Select”.

Under Edit Permissions:

  • As Effect, check Allow.
  • In AWS Service choose Amazon S3.
  • In “Actions” choose All Actions (*).
  • For Amazon Resource Name (ARN) enter arn:aws:s3:::name_of_app-assets.

It should look like this:

Image for post
Image for post

Go to “Users” →“Add User”, check the “Programmatic access” box and go to the next step.

Under “Set Permissions” → “Add user to group”, check the box related to the group your just created.

Go to the next step and simply click on “Next: Review” and finally “Create User”.

Download the .csv and/or write down the “Access key ID” and “Secret access key”, you will need them in your app configuration.

Go back to your account home page and this time search for S3. Under this service we will create a bucket where we will upload and store the static files.

Image for post
Image for post

Under “S3 Buckets”, click on “Create a bucket”, enter the name of your bucket, the most logical would be name_of_app-assets and select a region of your choosing, then click on “Next” until you have the “Create bucket” button.

Then click on your bucket, and upload the static files that will be used by your app.

Now to configure your app, first install the following packages to use AWS’s S3 with Django:

$ pip install django-storages boto3

Then edit your name_of_app/settings.py and put storages in installed apps as well as AWS S3 configuration variables:

INSTALLED_APPS = [
...
'storages',
]
AWS_ACCESS_KEY_ID = config(‘AWS_ACCESS_KEY_ID’)
AWS_SECRET_ACCESS_KEY = config(‘AWS_SECRET_ACCESS_KEY’)
AWS_STORAGE_BUCKET_NAME = config(‘S3_BUCKET_NAME’)
AWS_S3_CUSTOM_DOMAIN = AWS_STORAGE_BUCKET_NAME + ‘.s3.amazonaws.com’
AWS_QUERYSTRING_AUTH = False
DEFAULT_FILE_STORAGE = ‘storages.backends.s3boto3.S3Boto3Storage’
STATICFILES_STORAGE = ‘storages.backends.s3boto3.S3Boto3Storage’
#AWS S3 Static
AWS_STATIC_LOCATION = ‘static’
STATIC_URL = ‘https://' + AWS_STORAGE_BUCKET_NAME + ‘.s3.amazonaws.com/’
MEDIA_URL = STATIC_URL + ‘media/’
MEDIA_ROOT = MEDIA_URL
STATICFILES_DIRS = ( os.path.join(BASE_DIR, “static”), )
STATIC_ROOT = ‘staticfiles’
ADMIN_MEDIA_PREFIX = STATIC_URL + ‘admin/’
STATICFILES_FINDERS = (
‘django.contrib.staticfiles.finders.FileSystemFinder’,
‘django.contrib.staticfiles.finders.AppDirectoriesFinder’,
)

Using Heroku’s CLI, run the following commands to add the configuration values for your bucket and user:

heroku config:set AWS_ACCESS_KEY_ID=created_user_aws_key_id
heroku config:set AWS_SECRET_ACCESS_KEY=created_user_aws_secret_key
heroku config:set S3_BUCKET_NAME=name_of_app-assets

Disable Heroku’s automated collect static when building the app with:

heroku config:set DISABLE_COLLECTSTATIC=1

If you prefer to use Heroku’s dashboard, go to your app’s settings (at https://dashboard.heroku.com/apps/name_of_app/settings) and click on “Reveal Config Vars”. Add the new variables:

Don’t forget to put all of the new packages installed in your requirements file:

pip freeze > requirements.txt

Push all the changes to Heroku:

git push heroku master

Using programming for marketing and work efficiency

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store