So you've selected Python as your language of choice for building a massive web app. Congratulations! While there are some that will point to Python's relatively slow execution at runtime, you're brave enough to realize that saving chunks of your time is more important to the success of your project than building your app in a marginally faster language.

There are a few options when it comes to picking an out-of-the-box CMS with Django, but perhaps none are as popular as Django CMS. DjangoCMS is the biggest of the "big three" CMS choices for Django, with Mezzanine and Wagtail following close behind (I personally like Wagtail, if I'm gonna be real here).

As it stands, there doesn't seem to be an existing  guide which walks through the complete installation of Django + Django CMS. While is information exists in fragments, newcomers to Python could have trouble piecing much of this information together out of the gate. This guide hopes to serve as a reduction of friction to Django newcomers, thus ensuring Pythonic world domination.

Our Stack

To get this party started, our VPS is going to run the following stack:

  • Ubuntu
  • Python 3
  • Virtualenv
  • PostgreSQL
  • Django
  • Django CMS

Update All Dependencies

First, we'll prep our VPS with all the necessary dependencies:

$ apt-get update
$ apt-get upgrade -y
$ apt-get install python3 python3-pip python-dev libpq-dev postgresql postgresql-contrib

Create and Activate a Virtual Environment

Virtualenv is included with Python3, so no installation needed here.

$ virtualenv env
$ source env/bin/activate

Install Django

Find out what the latest distribution is by going here.

$ pip3 install Django==2.1.7

Install Django CMS

$ pip3 install django-cms

Start Project

Create a Django project in your desired directory.

$ cd /home
$ django-admin.py startproject yourproject

Update Settings.py File

We'll need to update settings.py with a few things.

$ cd yourproject/yourproject
$ vim settings.py

The resulting changes to settings.py are shown in the block below. These changes include:

  • Adding the first 4 lines in INSTALLED_APPS. These apps are specific to Django CMS.
  • Adding the LANGUAGES block.
  • Update the DATABASES block with your preferred database. We'll set up the corresponding database and database user later.
  • Add SITE_ID.
INSTALLED_APPS = [
    'django.contrib.sites',
    'cms',
    'menus',
    'treebeard',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

LANGUAGES = [
    ('en-us', 'English')
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'yourdb',
        'USER': 'youruser',
        'PASSWORD': 'yourpass123',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

SITE_ID = 1

Setting up PostgreSQL

In our case, we'll be using Postgres as our database. We already installed PostgreSQL earlier; the only thing left to install is Python's psycopg2 library for connecting to PostgreSQL databases:

$ pip3 install psycopg2

Activate the psql shell as the Postgres user:

$ su - postgres
$ psql

Create the Database and Database User

Create a database with a user, matching the information you entered in settings.py earlier:

CREATE DATABASE yourdb;
CREATE USER youruser WITH PASSWORD 'yourpass123';
ALTER ROLE youruser SET client_encoding TO 'utf8';
ALTER ROLE youruser SET default_transaction_isolation TO 'read committed';
ALTER ROLE youruser SET timezone TO 'EST';
GRANT ALL PRIVILEGES ON DATABASE yourdb TO youruser;

Exit the PostgreSQL user.

\q
exit

Migrate the Database Changes

Start the migration.

$ python3 manage.py migrate

Create a Superuser

Create a user for the CMS.

$ python3 manage.py createsuperuser

Validation

Make sure everything is ok.

$ python3 manage.py cms check

At this point, you might notice a few errors related to sekizai. We'll need to update a few more things.

Update Settings.py Again

We'll need to update settings.py with a few things.

Add 'sekizai' to INSTALLED_APPS.

INSTALLED_APPS = [
    'django.contrib.sites',
    'cms',
    'menus',
    'treebeard',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'sekizai',
]

Add an additional 5 lines to MIDDLEWARE:

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',
    'django.middleware.locale.LocaleMiddleware',
    'cms.middleware.user.CurrentUserMiddleware',
    'cms.middleware.page.CurrentPageMiddleware',
    'cms.middleware.toolbar.ToolbarMiddleware',
    'cms.middleware.language.LanguageCookieMiddleware',
]

Add 'sekizai.context_processors.sekizai', and 'django.template.context_processors.i18n', to TEMPLATES:

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',
                'sekizai.context_processors.sekizai',
                'cms.context_processors.cms_settings',
                'django.template.context_processors.i18n',
           ],
       },
    },
]

Finally, add your box's IP address to ALLOWED_HOSTS:

ALLOWED_HOSTS = [
    '000.000.00.00',
]

Update urls.py

Update urls.py to look like the following:

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('cms.urls')),
]

Give it a Go

Everything should be good! Start the app on port 8000 by entering the following:

$ python3 manage.py runserver 0.0.0.0:8000

The app should now be accessible at your box's IP address.