Get Started with Django on Scalingo
Requirements
Before doing this tutorial you should have setup your environment:
-
Setup the SSH authentication, it has to be done to let you
push
your application on the platform. - Install ‘scalingo’ Command Line Interface
Initialize Your Application
# Create your project
mkdir my-project
cd my-project
# Create a virtualenv
virtualenv venv
source venv/bin/activate
# Install Django and other useful packages:
pip install django django-environ psycopg gunicorn dj-database-url whitenoise
# Initialize Django project, this command will
# create a manage.py file and a myapp directory
django-admin.py startproject myapp .
Define How To Start Your Application
By default, the platform is looking for the web process type to start. You need
to specify how to start the applicative server, and define it to display logs
on stdout
to fit the 12-factor principles.
Using a WSGI Server
Create a file named Procfile
at the root of the project containing:
web: gunicorn myapp.wsgi --log-file -
Using a ASGI Server
In order to make use of a ASGI server such as Uvicorn, create a file named
Procfile
at the root of the project containing:
web: gunicorn myapp.asgi --worker-class=uvicorn.workers.UvicornWorker --log-file -
Compile .mo
Message Translation File
If you are using compilemessages
command to generate .mo
file for gettext
translations, that command needs to run before starting Gunicorn.
A solution would be to write a short start script (e.g. bin/start.sh
):
#!/bin/bash
python manage.py compilemessages
gunicorn myapp.wsgi --log-file -
Then in your Procfile
, directly call this script:
web: bash bin/start.sh
For more details, check the documentation about Procfile.
Python App Recognition and Dependencies Definition
The platform will understand that your app is a Python application if it
contains a requirements.txt
file at the root of the project. To create it,
your have to run the following command:
pip freeze > requirements.txt
Create Your Application and Databases on Scalingo
$ scalingo create myapp
- Go on the dashboard of your application.
- Select the Addons category
- Choose the database you want to use
PostgreSQL®
Nothing to do
MySQL®
By default, only the PostgreSQL® driver is installed, you need to replace it by the MySQL® driver.
pip uninstall psycopg
pip install mysqlclient
pip freeze > requirements.txt
Application Configuration
The configuration of the application has to be done through the environment variables, no credentials should be present statically in the code. It is usually a bad practice.
The configuration file in our example is located at myapp/settings.py
.
Ensure That the Base Directory of the Application Is Defined
Add (if not already set) the following definition after the top comment header
of the myapp/settings.py
file:
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
Configure the Database Access
Still in the myapp/settings.py
, replace:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
With:
import dj_database_url
try:
database_url = os.environ["DATABASE_URL"]
except KeyError:
database_url = "file:///{}".format(os.path.join(BASE_DIR, 'db.sqlite3'))
DATABASES = { 'default': dj_database_url.config() }
This has no effect on the default behavior. If no DATABASE_URL
has been set,
the application will fallback on your development backend, sqlite3. However, we
advise you to use the same database in development and in production to ensure
bug free migrations.
Static File Serving
In your settings configuration file myapp/settings.py
:
STATIC_ROOT = 'staticfiles'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
In the myapp/wsgi.py
file, replace
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
With
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
Cling
is part of the dj_static
module and is designed to serve static files.
If you don’t need to serve static files, you can setup the following environment variable:
DISABLE_COLLECTSTATIC=1
It will be taken into account during the next deployment of your application.
Configuration of Allowed Hosts
By default, Django will only serve requests coming for specific domain names to prevent HTTP Host header attacks. Without specifying these allowed domains, you will get the following error:
> Invalid HTTP_HOST header: '<domain>'. You may need to add '<domain>' to ALLOWED_HOSTS.
Consequently, you need to modify the settings.py
file. Replace this static
array:
ALLOWED_HOSTS = ["localhost"]
By this dynamic block reading the environment:
env_allowed_hosts = []
try:
env_allowed_hosts = os.environ["ALLOWED_HOSTS"].split(",")
except KeyError:
pass
ALLOWED_HOSTS = ["localhost"] + env_allowed_hosts
Then change the environment variable of your application with a coma-separated list of domains which will be used to access the app.
scalingo --app app-name env-set ALLOWED_HOSTS=app-name.osc-fr1.scalingo.io,example.com
Automatic Database Migrations
You can configure a postdeploy hook to migrate your database schema automatically after a deployment.
Database migrations in Django are separated in two steps:
-
python manage.py makemigrations
, which creates migrations files from model change -
python manage.py migrate
, which applies the migration file to the related database
Because makemigrations
modifies the source code, this command must be done on
your computer, and the created migration files committed to Git. This is not a
command to execute in your postdeploy hook.
The migrate
command is the one to execute to apply to migrations to your
database. You can add it to your Procfile
like this:
web: gunicorn mydjango.wsgi --log-file -
postdeploy: python manage.py migrate
Once your application is deployed, your migrations will be applied automatically.
Save Your App With Git
Setup .gitignore
You don’t want to keep track of everything on your version control system. To
prevent such files to be added to Git, create the file .gitignore
at the root
of your project with the following content:
venv
*.pyc
staticfiles
Commit Your Application
git init
git add .
git commit -m "Init Django application"
Deploy Your Application
git remote add scalingo git@ssh.osc-fr1.scalingo.com:myapp.git
git push scalingo master
Note that the remote URL depends on the region of your application. You can get it using our CLI with:
scalingo --app myapp git-show
Access Your Application
…
Waiting for your application to boot...
<-- https://myapp.osc-fr1.scalingo.io -->