Back to Blog
Tutorial

How to Deploy a Django Application in 1 Minute

Daniel Brooks6 min read
How to Deploy a Django Application in 1 Minute

Django is Python's most popular full-stack web framework, powering applications from startups to enterprises. Deploying Django to production requires proper security settings, static file handling, and WSGI server configuration.

With Out Plane, you can deploy your Django application in under a minute. This guide shows you exactly how.

What You'll Need

Before starting, make sure you have:

  • Python 3.10+ installed on your machine
  • A GitHub account
  • A Django application in a GitHub repository
  • A requirements.txt file with your dependencies

Don't have Python installed? Download it from python.org:

  • Windows: Download the installer and check "Add Python to PATH" during installation
  • macOS: Use brew install python3 or download from python.org
  • Linux: Run sudo apt install python3 python3-pip (Ubuntu/Debian) or sudo dnf install python3 (Fedora)

Once Python is installed, create a project folder and set up a virtual environment:

bash
mkdir my-django-app && cd my-django-app
python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install django gunicorn whitenoise

If you don't have a Django app yet, use our example below.

Quick Start: Sample Django Application

Create a new Django project with these commands:

bash
django-admin startproject myproject .
python manage.py startapp core

Update myproject/settings.py with production-ready settings:

python
import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

# Security settings from environment
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-secret-key-change-in-production')
DEBUG = os.environ.get('DEBUG', '0') == '1'

# Allow Out Plane domain and custom domains
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '*').split(',')

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'core',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',  # Static files
    '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 = 'myproject.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 = 'myproject.wsgi.application'

# Database - use PostgreSQL in production
DATABASE_URL = os.environ.get('DATABASE_URL')
if DATABASE_URL:
    import dj_database_url
    DATABASES = {'default': dj_database_url.parse(DATABASE_URL)}
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': BASE_DIR / 'db.sqlite3',
        }
    }

# Static files
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Create a simple view in core/views.py:

python
from django.http import JsonResponse

def home(request):
    return JsonResponse({
        "message": "Hello from Django!",
        "status": "running"
    })

def health(request):
    return JsonResponse({"status": "healthy"})

Update myproject/urls.py:

python
from django.contrib import admin
from django.urls import path
from core.views import home, health

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home),
    path('health/', health),
]

Create requirements.txt:

text
django==5.1.4
gunicorn==22.0.0
whitenoise==6.7.0
dj-database-url==2.1.0
psycopg2-binary==2.9.9

Create Procfile (no file extension):

text
web: gunicorn myproject.wsgi --bind 0.0.0.0:8080

This tells Buildpacks how to start your application with the Gunicorn WSGI server.

Push this code to a GitHub repository, and you're ready to deploy.

Optional: Add a Dockerfile

If you prefer full control over the build process, create a Dockerfile:

dockerfile
FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

RUN python manage.py collectstatic --noinput

EXPOSE 8080

CMD ["gunicorn", "myproject.wsgi", "--bind", "0.0.0.0:8080", "--workers", "4"]

With a Dockerfile, select Dockerfile as your build method. Without one, select Buildpacks and Out Plane handles everything automatically.

Deploy in 3 Steps

Step 1: Connect Your Repository

  1. Go to console.outplane.com
  2. Sign in with your GitHub account
  3. Select your Django repository from the list

Out Plane automatically detects Python applications and configures the build process using Buildpacks.

Step 2: Configure Your Application

Configure the following settings in the create application form:

Build Method

Select how Out Plane should build your application:

  • Buildpacks (Recommended): Automatically detects Python and installs dependencies from requirements.txt. Runs collectstatic automatically.
  • Dockerfile: Use this if you have a custom Dockerfile in your repository for full control over the build process.

For most Django applications, Buildpacks is the easiest option.

Basic Settings

  • Port: Set to 8080
  • Branch: Select main or your preferred branch
  • Region: Choose the region closest to your users

Environment Variables (Required)

Django requires certain environment variables for production. Add these using the Add button or Raw Edit:

text
SECRET_KEY=your-secure-random-string-here
DEBUG=0
ALLOWED_HOSTS=your-app.outplane.app,yourdomain.com

Generate a secure SECRET_KEY with:

bash
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"

Step 3: Deploy

Click Deploy Application and watch the build process:

  1. Queued → Waiting for resources
  2. Building → Installing dependencies, collecting static files
  3. Deploying → Starting your Django application
  4. Ready → Your app is live

Once the status shows Ready, your application is live. You can find your application URL at the top of the deployment page. Click the URL to open your Django app in a new tab. SSL is automatically configured.

Production Best Practices

Use Gunicorn for Production

Django's built-in server is not suitable for production. Always use Gunicorn:

bash
gunicorn myproject.wsgi --bind 0.0.0.0:8080 --workers 4

Out Plane's Buildpacks automatically detect Gunicorn in your requirements.txt and configure it properly.

Configure Workers

For better performance under load, customize the number of workers. A common formula is (2 × CPU cores) + 1.

If you need custom worker configuration, use a Dockerfile instead of Buildpacks for full control over the start command.

Static Files with WhiteNoise

WhiteNoise serves static files directly from your application without a separate web server:

  1. Add whitenoise to requirements.txt
  2. Add WhiteNoise middleware after SecurityMiddleware
  3. Set STATICFILES_STORAGE to use compressed storage
  4. Run collectstatic during build (automatic with Buildpacks)

Secure Your Settings

Never commit secrets to your repository:

python
# Good - read from environment
SECRET_KEY = os.environ.get('SECRET_KEY')
DEBUG = os.environ.get('DEBUG', '0') == '1'

# Bad - hardcoded values
SECRET_KEY = 'my-secret-key'
DEBUG = True

Connecting a Database

Most Django applications need a database. Out Plane provides managed PostgreSQL:

  1. Go to Databases in the sidebar
  2. Click Create Database
  3. Select PostgreSQL version and region
  4. Copy the connection URL

Add the connection URL as an environment variable:

text
DATABASE_URL=postgres://user:password@host/database

With dj-database-url in your requirements, Django automatically parses this URL:

python
import dj_database_url

DATABASE_URL = os.environ.get('DATABASE_URL')
if DATABASE_URL:
    DATABASES = {'default': dj_database_url.parse(DATABASE_URL)}

Run Migrations

After connecting your database, run migrations. You can add a release command to your Procfile:

text
release: python manage.py migrate
web: gunicorn myproject.wsgi --bind 0.0.0.0:8080

Or run migrations manually after deployment through your application's console.

Custom Domain Setup

Replace the default .outplane.app URL with your own domain:

  1. Navigate to Domains
  2. Click Map Domain
  3. Enter your domain (e.g., app.yourdomain.com)
  4. Add the DNS records shown to your domain registrar

Update your ALLOWED_HOSTS environment variable to include the new domain:

text
ALLOWED_HOSTS=your-app.outplane.app,app.yourdomain.com

SSL certificates are automatically provisioned once DNS propagates.

Monitoring Your Application

After deployment, monitor your Django application:

  • Logs: View real-time application logs including Gunicorn access logs
  • Metrics: Track CPU, memory, and network usage
  • HTTP Logs: Analyze incoming requests, response times, and status codes

Access these from the sidebar in your application dashboard.

Troubleshooting

Application Won't Start

Check the port configuration. Make sure you set the port to 8080 in the application settings and your Gunicorn command matches.

DisallowedHost Error

Update ALLOWED_HOSTS. Add your Out Plane domain to the environment variable:

text
ALLOWED_HOSTS=your-app.outplane.app

Static Files Not Loading

Verify WhiteNoise is configured. Check that:

  1. whitenoise is in requirements.txt
  2. WhiteNoise middleware is added after SecurityMiddleware
  3. STATIC_ROOT is set to a directory path
  4. collectstatic runs during build

Module Not Found Errors

Verify requirements.txt includes all dependencies. Run pip freeze > requirements.txt locally to capture all installed packages.

500 Internal Server Error

Check your application logs. Navigate to Logs in the sidebar to see Python tracebacks and error messages. Set DEBUG=1 temporarily to see detailed error pages.

Database Connection Failed

Verify DATABASE_URL format. Ensure the connection string follows this format:

text
postgres://username:password@hostname:port/database

Next Steps

Your Django application is now deployed and running in production. Here's what to explore next:

  • Scale your application: Adjust instance types and auto-scaling settings for higher traffic
  • Set up CI/CD: Enable automatic deployments on every git push
  • Add monitoring: Integrate with external monitoring tools via Out Plane's metrics export
  • Configure caching: Add Redis for session and cache storage

Summary

Deploying a Django application to Out Plane takes three steps:

  1. Connect your GitHub repository
  2. Configure port (8080), SECRET_KEY, and ALLOWED_HOSTS
  3. Deploy and get your live URL

No server configuration, no manual SSL setup, no infrastructure management. WhiteNoise handles static files automatically.

Ready to deploy your Django application? Get started with Out Plane and receive $20 in free credit.


Tags

django
python
deployment
tutorial
web-framework

Start deploying in minutes

Connect your GitHub repository and deploy your first application today. $20 free credit. No credit card required.