Deploy a Django Stack (Django + PostgreSQL)
The Flask tutorial covered a single-file app. This one deploys a real Django project against PostgreSQL as a Stack: the platform injects DATABASE_URL, and Django reads it via dj-database-url.
Result: visiting / shows Hello from Kuploy Stacks! Visits: N, incrementing on each refresh.
1. Get the code
Grab the ready-made project from kuploy/examples (subdir django-postgres):
git clone https://github.com/kuploy/examples
# project lives in examples/django-postgres
First complete the tutorial Prerequisites — a connected Git provider and a build registry — then connect the repo and set the build path as in Deploy Your First App.
The kuploy-relevant pieces are below; the rest is a standard django-admin startproject + one app.
requirements.txt
Django
psycopg[binary]
dj-database-url
gunicorn
mysite/settings.py (database)
import os
import dj_database_url
# DATABASE_URL is injected by the stack connection.
DATABASES = {
"default": dj_database_url.parse(os.environ["DATABASE_URL"]),
}
counter/views.py
from django.db import connection
from django.http import HttpResponse
def home(request):
with connection.cursor() as cur:
cur.execute("CREATE TABLE IF NOT EXISTS visits (count int)")
cur.execute("INSERT INTO visits (count) SELECT 0 WHERE NOT EXISTS (SELECT 1 FROM visits)")
cur.execute("UPDATE visits SET count = count + 1")
cur.execute("SELECT count FROM visits")
n = cur.fetchone()[0]
return HttpResponse(f"Hello from Kuploy Stacks! Visits: {n}")
Set ALLOWED_HOSTS = ["*"] (or your domain) in settings.py so Django serves behind the Kuploy ingress.
2. Choose a build method
Both run migrations on startup, after the stack deploys the database. See Build Methods.
- Dockerfile
- Nixpacks
The repo includes a Dockerfile:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
# Apply migrations, then serve. The stack deploys the database component first.
CMD ["sh", "-c", "python manage.py migrate && gunicorn -b 0.0.0.0:8000 mysite.wsgi"]
When you create the app, set Build Type → Dockerfile and enter Dockerfile in the Docker File field (required; relative to the build path).
Zero-config — Nixpacks auto-detects Django and installs requirements.txt. No Dockerfile needed. Add a nixpacks.toml so it migrates and serves under gunicorn:
[start]
cmd = "python manage.py migrate && gunicorn mysite.wsgi --bind 0.0.0.0:8000"
When you create the app, set Build Type → Nixpacks.
3. Create the services
In your project's environment:
- Create Service → Application named
web. The Set up your application wizard opens — walk the steps in order (or close it and use the service's tabs manually):- Source — point it at the examples repo, set Build Path
django-postgres. - Build — pick the Build Type you chose above.
- Network — set the port to 8000; add a domain if you want it public.
- Registry — select the registry from the prerequisites; without it the build has nowhere to push and the deploy fails with Registry required. (Skipped automatically for Docker-image sources or single-server deploys.)
- Deploy — stays disabled until source and registry are set. Don't deploy it yet.
- Source — point it at the examples repo, set Build Path
- Create Service → Database → PostgreSQL named
db(defaults are fine). Its internal connection string — shown on the db's General tab — ispostgresql://<user>:<password>@<db-app-name>:5432/<database>(the host is the service's app name; see Databases). The stack injects exactly this string asDATABASE_URL.
4. Group them into a stack
- Environment toolbar → Stacks → Create stack, name it
visits, open it. - Add component → add
web, thendb.
5. Connect
Drag from db to web (or click Connect):
- Provider:
db - Source field:
connectionString - Consumer:
web - Env var name:
DATABASE_URL
dj-database-url parses it into Django's DATABASES setting.
6. Deploy
Click Deploy stack — db deploys first, then web (which runs migrate against the now-ready database on startup). Open the app's domain; refresh and the counter climbs.
The web service's Environment tab shows a managed block with the resolved DATABASE_URL.
What you learned
- The same stack connection that works for a one-file Flask app drives a full Django project — Django just consumes
DATABASE_URLviadj-database-url. - Database migrations run on the web component at startup, after the stack has deployed the database.