Deployment: WSGI, Static & Settings

Deployment is the process of configuring and running your Django project on a production server safely, with debugging off, secrets in the environment, static files collected, and a real WSGI server handling requests.

Learn Deployment: WSGI, Static & Settings in our free Django course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…

Part of the free Django course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll harden settings with DEBUG=False , ALLOWED_HOSTS , and an environment-driven SECRET_KEY , collect static files with collectstatic and WhiteNoise, serve the app through gunicorn and WSGI, parse a database URL, and run the deploy checklist.

What You'll Learn in This Lesson

1 Production Settings from the Environment

The most important production change is turning DEBUG off and listing your real domains in ALLOWED_HOSTS . Secrets like SECRET_KEY must come from the environment, never from a file in your repository. You read them with os.environ at startup.

2 Static Files, the Database URL, and gunicorn

In production the dev server doesn't serve static files, so you run collectstatic to gather them into STATIC_ROOT and let WhiteNoise serve them. Your database connection arrives as a single DATABASE_URL , and you run the app through gunicorn , which loads your project's WSGI callable.

3 The Deploy Checklist (check --deploy)

Django ships a built-in safety audit: python manage.py check --deploy . It inspects your settings and warns about anything unsafe for production — DEBUG left on, an empty ALLOWED_HOSTS , a weak SECRET_KEY , or missing SSL settings. Run it before every release.

🎯 Your Turn: Read DEBUG from the Environment

Environment variables are strings, so "False" is truthy. Fill in the blank so DEBUG becomes the boolean False only when the variable is exactly "True" .

Common Errors (And How to Fix Them)

❌ DisallowedHost / Bad Request (400) after deploy

With DEBUG=False , Django rejects any host not listed in ALLOWED_HOSTS .

✅ Fix: add your domain(s) to ALLOWED_HOSTS , e.g. ["example.com", "www.example.com"] .

You never collected static files, or nothing is serving them.

✅ Fix: run collectstatic and add WhiteNoise middleware (or a CDN) to serve STATIC_ROOT .

A hard-coded SECRET_KEY in settings.py ends up in version control.

✅ Fix: read it from os.environ and store the value in your platform's secret manager.

📋 Quick Reference

Setting / Command

Why It Matters

DEBUG = False

Hide tracebacks; enforce ALLOWED_HOSTS

ALLOWED_HOSTS

Domains the site is allowed to serve

collectstatic

Gather static files into STATIC_ROOT

gunicorn project.wsgi

Run the app as a WSGI server

check --deploy

Audit settings for production safety

🏆 Mini Challenge: A Deploy-Readiness Gate

Build a gate that loads settings from the environment, runs the production checklist, and only "deploys" when there are zero issues — otherwise it reports the blocking problems.

❓ Frequently Asked Questions

Lesson complete — you can ship to production!

You can harden settings with DEBUG=False , ALLOWED_HOSTS , and an env-driven SECRET_KEY , collect static files with collectstatic and WhiteNoise, run the app through gunicorn and WSGI, parse a database URL, and audit with check --deploy .

🚀 Up next: Checkpoint — Build a Django REST API — put pagination, auth, and caching together in one project.

Practice quiz

What must DEBUG be set to in production?

  • True
  • False
  • 1
  • 'on'

Answer: False. DEBUG=False hides tracebacks, enforces ALLOWED_HOSTS, and serves a generic 500 page.

Why is DEBUG=True dangerous in production?

  • It makes the site slower only
  • It disables the database
  • It exposes code, settings, and environment in error pages
  • It blocks all requests

Answer: It exposes code, settings, and environment in error pages. The debug error page leaks code, settings, and env vars to anyone who triggers an error.

What does collectstatic do?

  • Compiles your Python code
  • Gathers static files into STATIC_ROOT
  • Minifies JavaScript only
  • Starts the web server

Answer: Gathers static files into STATIC_ROOT. collectstatic gathers static files from all apps into the single STATIC_ROOT directory.

What is WSGI?

  • A database driver
  • A template engine
  • A caching backend
  • The standard interface between a Python web app and a server

Answer: The standard interface between a Python web app and a server. WSGI is the standard interface; project/wsgi.py exposes the 'application' callable.

Which command starts a production WSGI server for project/wsgi.py?

  • gunicorn project.wsgi:application
  • python manage.py runserver
  • django-admin serve
  • wsgi start project

Answer: gunicorn project.wsgi:application. gunicorn imports the WSGI application callable and serves it with worker processes.

What does WhiteNoise let you do?

  • Encrypt the database
  • Serve collected static files efficiently from the app server
  • Run background tasks
  • Manage migrations

Answer: Serve collected static files efficiently from the app server. WhiteNoise serves the collected static files with caching headers, the simplest production option without a CDN.

Why must ALLOWED_HOSTS be set when DEBUG=False?

  • It speeds up rendering
  • It configures static files
  • Django rejects any host not listed, raising DisallowedHost
  • It enables the admin

Answer: Django rejects any host not listed, raising DisallowedHost. With DEBUG off Django enforces ALLOWED_HOSTS and returns 400 for unlisted hosts.

How should SECRET_KEY be supplied in production?

  • Hard-coded in settings.py
  • Committed to the repository
  • Generated fresh on every request
  • Read from an environment variable, never committed

Answer: Read from an environment variable, never committed. Read SECRET_KEY from os.environ and keep it out of source control.

Which command audits settings for production safety?

  • python manage.py check --deploy
  • python manage.py audit
  • python manage.py secure
  • python manage.py validate

Answer: python manage.py check --deploy. check --deploy warns about DEBUG, empty ALLOWED_HOSTS, weak SECRET_KEY, and missing SSL settings.

Why compare an env var explicitly with == 'True' for DEBUG?

  • It is faster than bool()
  • Env vars are strings, so even 'False' is truthy
  • Django requires the string form
  • It avoids importing os

Answer: Env vars are strings, so even 'False' is truthy. Environment values arrive as strings; any non-empty string is truthy, so compare to 'True'.

Continue this course