New greener region discount. Save 3% on Upsun resource usage. Learn how.
LoginFree trial
FeaturesPricingBlogAbout us
Blog

Up(sun) and running with Django

DjangoCLIconfigurationPython
21 December 2023
Chad Carlson
Chad Carlson
Senior Manager, Developer Relations

Looking to get started with Upsun and Python? The Upsun CLI contains a command called project:init designed  to get you started on Upsun  with a number of frameworks—including Django—as quickly as possible.

Setting up

Let’s start with a simple Django codebase, in this case using the popular Python templating utility cookiecutter: 

cookiecutter https://github.com/cookiecutter/cookiecutter-django

The cookiecutter CLI will prompt you to answer a series of questions about email, CI tools, and IDE. Answer according to your preference, but be sure to:

  • Select the latest version of PostgreSQL for your database
  • Select “Other SMTP” for the mail service
  • Include the Django Rest Framework (“use drf”)
  • Pick “Webpack” for your frontend pipeline
  • Include “Whitenoise”
  • Use “Celery”

After finishing the prompts, you’ll have a new skeleton project in whichever directory you passed as the name (in the examples below, new_project):

.
├── README.md
├── bin
├── compose
├── config
|   ├── __init__.py
|   ├── api_router.py
|   ├── celery_app.py
|   ├── settings
|   |   ├── __init__.py
|   |   ├── base.py
|   |   ├── local.py
|   |   ├── production.py
|   |   └── test.py
|   ├── urls.py
|   └── wsgi.py
├── docs
├── locale
├── manage.py
├── new_project
|   ├── __init__.py
|   ├── conftest.py
|   ├── contrib
|   ├── static
|   ├── templates
|   ├── users
|   └── utils
├── package.json
├── requirements
├── requirements.txt
├── setup.cfg
├── tests
└── webpack

With the project in place, we can then generate a first draft of our Upsun configuration using the CLI:  

cd new_project && upsun project:init

Follow the prompts to include configuration for both PostgreSQL and Redis. This command will automatically detect the Django project based on the presence of a manage.py file, and generate two pieces of configuration: an environment file and a primary configuration YAML file.

The .environment file at the root of the project which will be created, sets environment variables that the cookiecutter project needs. You can inspect this file yourself, but a few important pieces that become available include general Django project settings:

# .environment

export DJANGO_SETTINGS_MODULE=config.settings.production
export DJANGO_SECRET_KEY="$PLATFORM_PROJECT_ENTROPY"
export DJANGO_ALLOWED_HOSTS=".platformsh.site"

This section appends Django’s allowed hosts to include all URLs generated for Upsun preview environments, to update Django’s secret key to match the unique project hash, and to leverage production settings (in this case) across all Upsun environments.

Additional credentials are expanded from built-in environment variables to establish connections with managed services provided by Upsun:

# .environment

# Set database environment variables
export DB_HOST="$POSTGRESQL_HOST"
export DB_PORT="$POSTGRESQL_PORT"
export DB_PATH="$POSTGRESQL_PATH"
export DB_USERNAME="$POSTGRESQL_USERNAME"
export DB_PASSWORD="$POSTGRESQL_PASSWORD"
export DB_SCHEME="$POSTGRESQL_SCHEME"
export DATABASE_URL="${DB_SCHEME}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_PATH}"

# Set Cache environment variables
export CACHE_HOST="$REDIS_HOST"
export CACHE_PORT="$REDIS_PORT"
export CACHE_SCHEME="$REDIS_SCHEME"
export CACHE_URL="${CACHE_SCHEME}://${CACHE_HOST}:${CACHE_PORT}"

# Set Redis environment variables
export REDIS_URL="$CACHE_URL"# Celery
export CELERY_BROKER_URL="$CACHE_URL"# General

An .upsun/config.yaml file is also added that configures build, deploy, and available services for the project. It includes configuration for the services you selected via prompts:

# .upsun/config.yaml

services:
    postgresql:
        type: postgresql:15
    redis:
        type: redis:7.0

Application configuration is also added. It defines how Django is built and deployed via pip, how access is granted to the above services via relationships, and how to run the server with Gunicorn:

# .upsun/config.yaml

applications:
    new_project:
        type: "python:3.11"
        hooks:
            build: |   
                set -eux
                pip install --upgrade pip
                pip install -r requirements.txt
                npm install
                npm run build
            deploy: |   
                set -eux
                python manage.py collectstatic --noinput
                python manage.py migrate
        web:
            commands:
                start: "gunicorn -b unix:$SOCKET config.wsgi"
            upstream:
                socket_family: unix
            locations:
                    "/":
                        "passthru": true
                    "/static":
                        "allow": true
                        "expires": "1h"
                        "root": "static"
        mounts:
            "/staticfiles":
                "source": "local"
                "source_path": "static_assets"
        relationships:
            postgresql: "postgresql:postgresql"
            redis: "redis:redis"

With these two pieces of configuration, we can create a new project and deploy Django on Upsun:

$ git add . && git commit -m  “Prepare for Upsun!”
$ upsun project:create 
$ upsun push

With this production environment deployed, we can now adjust the resources provided to that environment with the CLI command upsun resources:set.

Next steps

You may have noticed that the cookiecutter project expected credentials to configure connect to Redis to run Celery to manage tasks for the application. We included an environment variable to connect but didn’t specify how to actually run that service.

We can now create a new preview environment that can match production with respect to its build images, containers, data, and resources as much as we’d like.

$ upsun branch try-celery --type staging

From this environment we can once again commit and push, with some Celery workers defined:  

# .upsun/config.yaml
applications:
    new_project:

        ...

        workers:
           celery_worker:
               commands:
                   start: "celery -A config.celery_app worker"
           celery_beat:
               commands:
                   start: "celery -A config.celery_app beat"

Test the connection and performance of the workers in the isolated environment, and then when you’re satisfied promote the new workers to production:

$ upsun merge try-celery

And just like that, your next Django project is up, running, and ready to go!

Upsun Logo
Join the community