This content originally appeared on DEV Community and was authored by Piko
From Localhost to Live: The Essential Django Deployment Guide
You’ve done it. You’ve built a Django app, and it’s running beautifully on your local machine with its virtual environment and all dependencies installed. Now comes the big question: how do you get this thing ready for the world to see?
Deploying a Django app isn’t just about copying files to a server. It’s about transforming your development setup into a secure, efficient, and reliable production environment. This guide will walk you through the essential steps to bridge that gap.
The Golden Rule: Never Hardcode Secrets
Before we touch anything, let’s establish the most important principle: separate your configuration from your code. Your production environment will have different settings than your local one (different databases, secret keys, debug settings). Hardcoding these values is a recipe for security risks and deployment headaches.
The solution is to use environment variables. We’ll store our configuration in the hosting environment and have Django read from there.
For local development, we can simulate this with a .env
file and the python-dotenv
library.
-
Install the library:
pip install python-dotenv
-
Create a
.env
file in your project’s root (the same level asmanage.py
):
# .env DEBUG=True SECRET_KEY=your-insecure-local-secret-key DATABASE_URL=sqlite:///db.sqlite3
Important: Add
.env
to your.gitignore
file immediately! This file should never be committed to version control.
Step 1: Production-Proof Your settings.py
Now, let’s modify your settings.py
to read from these environment variables.
1.1 Load Environment Variables
At the top of your settings.py
, add the following to load the .env
file (it won’t do anything in production, which is what we want).
# settings.py
import os
from dotenv import load_dotenv
load_dotenv()
1.2 Secure SECRET_KEY
and DEBUG
Replace your hardcoded SECRET_KEY
and DEBUG
values.
# settings.py
# Pull the SECRET_KEY from the environment
SECRET_KEY = os.getenv("SECRET_KEY")
# Set DEBUG to False unless explicitly set to "True" in the environment
DEBUG = os.getenv("DEBUG", "False").lower() == "true"
1.3 Configure ALLOWED_HOSTS
In production, you must tell Django which domain(s) are permitted to host your app.
# settings.py
# We'll get the actual domain from our hosting provider later
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "localhost,127.0.0.1").split(",")
# Important for security when running on HTTPS
CSRF_TRUSTED_ORIGINS = os.getenv("CSRF_TRUSTED_ORIGINS", "http://localhost").split(",")
Step 2: Bring in the Production Stack
Your development server and database aren’t cut out for production traffic. Let’s bring in the right tools for the job.
2.1 Use a Production WSGI Server: Gunicorn
The manage.py runserver
command is only for development. For production, you need a robust WSGI server. Gunicorn (Green Unicorn) is a popular and reliable choice.
pip install gunicorn
2.2 Serve Static Files with WhiteNoise
When DEBUG
is False
, Django stops serving static files (your CSS, JavaScript, and images). WhiteNoise is the easiest way to get your app to serve its own static files securely and efficiently.
-
Install WhiteNoise:
pip install whitenoise
-
Configure in
settings.py
:- Add WhiteNoise to your middleware, right after the
SecurityMiddleware
. - Set the
STATIC_ROOT
and configure the staticfiles storage backend.
# settings.py MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', # Add this line # ... other middleware ] # This is where collectstatic will gather all static files STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # This improves performance by caching and compressing files STORAGES = { "staticfiles": { "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", }, }
- Add WhiteNoise to your middleware, right after the
2.3 Switch to a Production Database: PostgreSQL
SQLite is a single-file database that can’t handle concurrent requests well, making it unsuitable for most production sites. PostgreSQL is a powerful, open-source database that’s a standard choice for Django apps.
To make connecting easy, we’ll use dj-database-url
and psycopg2-binary
.
-
Install Packages:
pip install psycopg2-binary dj-database-url
-
Configure in
settings.py
:
This will read your database connection string from a singleDATABASE_URL
environment variable. It cleverly defaults to your existing SQLite setup if the variable isn’t found.
# settings.py import dj_database_url # ... at the bottom of the file ... DATABASES = { 'default': dj_database_url.config( # Default to SQLite if DATABASE_URL is not set default=f"sqlite:///{os.path.join(BASE_DIR, 'db.sqlite3')}" ) }
Step 3: Automate Your Deployment Tasks
You need to perform the same set of tasks every time you deploy: install packages, collect static files, and run migrations. Let’s automate this with a simple build script.
Create a file named build.sh
in your project’s root:
#!/bin/bash
# Exit immediately if a command exits with a non-zero status.
set -e
# Install Python dependencies
pip install -r requirements.txt
# Run Django's collectstatic to gather static files
python manage.py collectstatic --no-input
# Apply any database migrations
python manage.py migrate
Now, make the script executable: chmod +x build.sh
Final Preparations
You’re almost there!
-
Update
requirements.txt
: Your virtual environment now has Gunicorn, WhiteNoise, and other production packages. Update your requirements file to reflect this.
pip freeze > requirements.txt
Push to Git: Commit all your changes and push them to your GitHub (or GitLab) repository. Your code is now fully prepared for deployment.
Time to Deploy!
Now you can head to your hosting platform of choice (like Seenode, Heroku, Render, etc.). The process will generally be:
- Connect Your Repo: Link the platform to your GitHub repository.
- Set Build & Start Commands:
- Build Command:
./build.sh
- Start Command:
gunicorn movie_spot.wsgi --bind 0.0.0.0:80
(Replacemovie_spot
with your project’s name).
- Build Command:
- Set Environment Variables: This is where you’ll add your production
SECRET_KEY
, setDEBUG
toFalse
, and provide theDATABASE_URL
from the PostgreSQL database you create on the platform. You’ll also set your live domain inALLOWED_HOSTS
andCSRF_TRUSTED_ORIGINS
.
And that’s it! With these steps, you’ve taken your Django project from a local development build to a secure, robust, and production-ready application.
Are you a visual learner?
I’ve created a complete video walkthrough of this deployment guide. Watch and code along as we take our project from localhost to a live, production-ready application on the cloud.
Happy deploying
This content originally appeared on DEV Community and was authored by Piko