PreviewDrop for Django

Deploy previews for Django apps

Push a branch, get a live preview URL. PreviewDrop builds your Django container and posts the link to the pull request, usually within a couple of minutes — no CI scripts, no serverless adapters.

TL;DR
Connect your repo, push. PreviewDrop detects Django, builds the image and posts a TLS-terminated preview URL to the PR — add your migrations to the Start command to run them on boot. Gunicorn runs exactly as it does in production — no Django-to-Lambda adapters, no 10-second function limits on views, no cold starts.

What the build needs to do

You don't write this. PreviewDrop detects Djangofrom your repo and builds the container for you — a Dockerfile in your repo is not used. The reference below shows the install, build and start steps a working Django image needs. If detection gets one wrong, set the matching Install, Build or Start command in Project Settings. Your app must listen on $PORT.

Reference (not read by PreviewDrop)
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 8000 # Replace "myapp" with the folder that contains your wsgi.py CMD sh -c "python manage.py migrate --noinput && gunicorn myapp.wsgi:application --bind 0.0.0.0:${PORT:-8000} --workers 2"

Environment variables

Set these in the Variables tab of your PreviewDrop project. They're encrypted at rest and injected into every preview container at start.

VariableExample valueNote
SECRET_KEYdjango-insecure-replace-meAny long random string. Never reuse your production key.
DEBUGTrueFine for preview environments — always False in production.
ALLOWED_HOSTS.previews.previewdrop.dev,localhostThe leading dot is a Django wildcard — covers every auto-generated preview subdomain.
DATABASE_URLpostgres://user:pass@host:5432/dbPoint at a shared dev DB, or omit to use SQLite (fine for UI-only previews).

Common gotchas

ALLOWED_HOSTS must include .previews.previewdrop.dev

Django returns a 400 for requests from unknown hosts. Set ALLOWED_HOSTS=.previews.previewdrop.dev,localhost in your project variables. The leading dot is a Django wildcard that matches every auto-generated preview subdomain without needing to know the URL in advance.

Point the Start command at your project

The reference Start command uses myapp.wsgi:application. Replace myapp with the name of the Django project directory that contains your wsgi.py — usually the same as the root project folder name.

gunicorn must be in requirements.txt

The image only installs what's in requirements.txt. If gunicorn isn't listed there the Start command will fail at startup. Add gunicorn>=21.2 if it's missing.

Static files: run collectstatic in the Build command

Run python manage.py collectstatic --noinput in the Build command (Project Settings) so assets are baked into the image. To serve them without a CDN, add whitenoise to MIDDLEWARE and set the whitenoise storage backend in STATICFILES_STORAGE.

Why not Vercel or Netlify?

Vercel doesn't run Django natively. Community adapters exist that wrap WSGI in a Lambda function, but you lose long-running request support, Celery workers, and manage.py access. Netlify has the same constraint — their Functions runtime is Node/Deno/Go, not Python WSGI. PreviewDrop runs your app in a real container: Gunicorn, background workers, migrations at startup — the same container shape as your production environment, used as a PR deploy preview.

Preview your Django app in 5 minutes

Connect a repo, push a branch, get a URL. No credit card, no trial clock.

Start free