PreviewDrop for Django

A live Django preview for every branch

Django apps run end-to-end on PreviewDrop: migrations, Celery workers, Channels websockets, admin site — the same container you'd push to prod. No serverless re-architecture.

TL;DR
Drop a Dockerfile at the root of your Django repo, set ALLOWED_HOSTS and DATABASE_URL in the Variables tab, push a branch. 5 minutes to your first preview URL. Works with Django 4.x and 5.x, Python 3.10+.

Dockerfile

Drop this at the root of your repo. PreviewDrop picks it up on the next push and builds it into a container behind a TLS-terminated subdomain.

Dockerfile
FROM python:3.12-slim WORKDIR /app RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential libpq-dev \ && rm -rf /var/lib/apt/lists/* COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD ["sh", "-c", "python manage.py migrate --noinput && \ gunicorn project.wsgi --bind 0.0.0.0:$PORT --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
DATABASE_URLpostgres://user:pass@dev-db.internal/myappPoint every preview at a shared dev DB, or use a per-branch DB with Neon.
DJANGO_SECRET_KEY<random 50 chars>Generate once, store in Variables tab. Never commit to git.
DJANGO_DEBUGTrueFine for previews. Never set True in production.
ALLOWED_HOSTS.previews.previewdrop.devCovers every PreviewDrop subdomain in one glob.
CSRF_TRUSTED_ORIGINShttps://*.previews.previewdrop.devDjango 4.1+ — required for form posts to work.

Common gotchas

ALLOWED_HOSTS mis-set

The single most common Django preview failure. Set ALLOWED_HOSTS=.previews.previewdrop.dev — the leading dot matches any subdomain. Without this, Django answers every request with DisallowedHost and the preview looks broken.

Static files

Run python manage.py collectstatic --noinputin your Dockerfile's build step and use WhiteNoise (pip install whitenoise) to serve them without nginx in front. WhiteNoise is the standard pattern for containerised Django and works perfectly in previews.

Migrations on every deploy

The Dockerfile above runs manage.py migrate at container start. Safe for previews pointed at a dedicated dev DB; risky if every preview shares a DB and someone merges a destructive migration. For isolated preview DBs, pair PreviewDrop with Neon branching — each Git branch gets its own Postgres branch automatically.

Celery workers

If your app needs Celery, the cleanest pattern is a second PreviewDrop project pointed at the same repo with a Dockerfile.worker that runs celery -A project worker. Both projects share the same env vars (including your Redis URL) so they coordinate via the broker.

Why not Vercel or Netlify?

Vercel doesn't run Django as a first-class citizen. You can route Django through a serverless function (django-verceladapters exist), but you give up Celery workers, long-running Channels websockets, and you fight a 10-second execution limit on every view. PreviewDrop runs the exact container you'd push to prod — if it works on your laptop in Docker, it works here.
More Django patterns
Frameworks & Docker has the full guide. For branch-isolated DBs, see Environment variables.

Preview your Django app in 5 minutes

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

Start free