-
Notifications
You must be signed in to change notification settings - Fork 8
Django Heroku direct configuration training
Latest update: March 2018
Your contribution is appreciated: If you find errors / mistakes / information that is not updated, please report it on the repository issue. This guide is subjected to update based on the tools, dependencies and features involved.
NOTE:
- If you have successfully deploy a Django project to Heroku without any help tools (like travisCI), you may ignore this section. Many new members might have problems with the deployment to Heroku. So, this is a guide to help you figure out what is wrong with your deployment settings by providing a deeper understanding into the code settings of a Django project.
- Specific configuration setting for packages may differ from each other. A new update on each package may also affect the configuration settings. check the time of the most recent update on this Wiki.
This guide was developed based on this video, video part 1 to 3, and Heroku documentation.
Configuration used the following modules/packages:
- whitenoise (free version)
- Django
- gunicorn
Configuration for the following files:
wsgi.py
settings.py
-
static
andtemplates
directory
- Go to your directory where
manage.py
exist (should be created when you create the project) - run
python manage.py runserver
- the terminal tell you the local server such as
http://127.0.0.1:8000/
(your local server might differ) copy and paste this to your browser. if it works, you should see the default Django page that says "Congratulations on your first Django-powered page"
notice that if you go to the admin/
url, you will be directed to the Django admin panel (http://127.0.0.1:8000/admin
). This is defined in your wsgi.py
.
You need to have a directory to store you static
directory (such as CSS, fonts, image, etc) and templates
directory. Django required you to have the directory in the exact wordings (case sensitive).
once you get used to Django configuration, you may freely organize your directories in your own fashion. However, many programmers adopted the following directory structure as a standard because it appeared to be neat:
- app
- static
- templates
- project_name
settings.py
__init__.py
urls.py
wsgi.py
manage.py
Procfile
requirements.txt
runtime.txt
static: where you place your CSS, Fonts, Image, etc. (When you deal with many files, you would want each of these to be a separate folder. for now, you can place your CSS file in the static folder)
templates: where you placed all the HTML files.
This is where the webserver will start. after you created the Django project, you will get the following code in your wsgi.py
"""
WSGI config for demo project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
application = get_wsgi_application()
the above code basically telling the webserver to look into settings.py
as the next step.
since you will be using the whitenoise package, add the following lines
from whitenoise.django import DjangoWhiteNoise
application = DjangoWhiteNoise(application)
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
The above lines is the default Django admin url. This is the place where you define a certain url to direct user to a certain page. if you had accessed the Django admin panel before using the http://127.0.0.1:8000/admin
, that was the result of the above configuration of the urls.py
.
Typical deployment problem: you are not routing the files directory correctly in your settings.py
, don't get frustrated easily.
Tips: Try to focus debugging your configuration on how your files are organized and how you are routing to each of the necessary files in your settings.py
when you create your a Django Project, you get a settings.py
. Think of the following code like a skeleton file for configuration.
"""
Django settings for testing project.
Generated by 'django-admin startproject' using Django 1.11.9.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '!dhcizt49yjgk)e1fw%uw4_3m^qaj)fyzheymm+k_trfv8jk9s'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'testing.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'testing.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
to log in simply
heroku login: <your Heroku user name>
to specify the name of your app. your app will be created under your_app_name.herokuapp.com
heroku create: <your_app_name>
- you have HTML, CSS and Javascript file ready in your local repository.
- you have pip installed
- you are trying to do simple deployment of your HTML page to heroku using django configuration.
- you have vim installed so all file editing is done in vim mode.
- you have created a Django project
- the file and folders organization follows this youtube video which was seemed to be the best practice at the time of this writing.
virtualenv <your virtual environment name>
example,
virtualenv env
a venv
is created in your current directory
purpose: this virtual environment is used to isolate your environment when installing python modules. without this venv, you will install all python modules (can be identified as a long list in the requirements.txt
file after you do the installation). with this venv, you basically install just the necessary modules. too many unnecessary modules might cause errors because Heroku will pull all the modules specified in requirements.txt
(not recommended).
source <your virtual environment name>/bin/activate
example,
source venv/bin/activate
modules that you need to install:
- whitenoise
- django
- gunicorn
pip install whitenoise
pip install gunicorn
pip freeze > requirements.txt
Then, check you new requirements.txt after you exit the virtual mode.
deactivate
you should see your requirements.txt containt modules similar to the following (version of each modules does not need to be exactly the same):
Django==1.11.10
gunicorn==19.7.1
pytz==2017.3
whitenoise==3.3.1
potential problems:
- sometimes you might find more modules were being installed. try to deploy first without deleting the modules other than the modules written in the above instruction. if error occur, you can try delete the modules that were not part of the four modules above
create a file runtime.txt
and place your python version. Heroku will use this to identify the python version that must be used. for an updated documentation of which python version being supported by Heroku, check 'Heroku specifying Python Runtime document'
to check you python version,
python --version
for python 3 version,
python3 --version
edit runtime.txt
and write the python version using the following format
python-3.5.2
if you have done the 'getting started on Heroku with Python' you should know this is an important part of Heroku and Django configuration
follow this step as it's not defined clearly in Heroku documentation at the time of this wiki was being written
create a file name Procfile
. Make sure it's exactly the same (case sensitive).
vim Procfile
write the file exactly as follows
web: gunicorn <the name of your root folder>.wgsi --log-file -
for example (root folder is demo
),
web: gunicorn demo.wsgi --log-file -
potential problem:
- incorrect
Procfile
definition would result in a certain deployment failure - your
.wsgi
file was not directed correctly insettings.py
this will help you understand structure within the settings.py
of Django configuration.
-
DEBUG = true
:Instruction: This wouldn't be a major issue since you're working on a demo for now so don't change this line after you created the django project.
However, it's imperative that you understand this is where you set whether your code could be access from client side or not. it is recommended that you set it to
false
so that your code is not exposed to the public, compromising your app security. Some claimed that it had been an issue so for now you can set it totrue
. [This is still subjected to changes].Potential problems:
- try leaving the default state did not work? try doing the opposite. if what you got was
DEBUG = true
, try switching it to false. and remember to take note of the changes you made.
- try leaving the default state did not work? try doing the opposite. if what you got was
-
ALLOWED_HOSTS = []
Django HTTP host header:
This is where you define the domain and hosts for you to have access to the app. even when you're testing locally, you still need to define it as a
string
type. an example would be as follows,ALLOWED_HOSTS = [ 'time-map7-1.herokuapp.com', '127.0.0.1', 'localhost' ]
Potential problem that needs attention:
- Host header poisoning security issue - issue raised in 2013 - (new members can ignore this part for now).
-
INSTALLED_APPS[]
:This is where you want to add the directory of where your
static
andtemplate
directories exist. you will need a directory of that are namedstatic
andtemplate
exactly. if you mistype this, the web server will not be able to find static and templates, which then it will throw errors.following the [directory structure](# MyProject-(root-folder) above, add the directory name in
string
format into the list'app'
resulting,
# Application definition INSTALLED_APPS = [ 'app', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
More details:
INSTALLED_APPS
is directing to your application directory so that the web server can install your application. in this case, your application is a static web page that is in theapp
directory. As you can see there are other applications created by Django. -
MIDDLEWARE = []
:whitenoise configuration:
'whitenoise.middleware.WhiteNoiseMiddleware',
example,
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', ]
-
Static files (CSS, Javascript, Images)
make sure you have the following at the end of
settings.py
# Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' STATIC_URL = '/static/' STATIC_ROOT = os.path.join((BASE_DIR), 'static')
This should be enough for you to start deploying a simple HTML page and CSS file. You can also refer back to two of the videos stated in the beginning of this guide.