Django's built-in development server is a lightweight, auto-reloading server designed for development and testing. This comprehensive guide covers everything you need to know about running, configuring, and optimizing the development server for productive Django development.
Basic Usage:
# Start server on default port (8000)
python manage.py runserver
# Expected output:
# Watching for file changes with StatReloader
# Performing system checks...
# System check identified no issues (0 silenced).
# November 15, 2024 - 10:30:45
# Django version 4.2.7, using settings 'myproject.settings'
# Starting development server at http://127.0.0.1:8000/
# Quit the server with CONTROL-C.
Custom Port and Host:
# Custom port
python manage.py runserver 8080
# Custom host and port
python manage.py runserver 0.0.0.0:8000
# Bind to all interfaces (accessible from network)
python manage.py runserver 0.0.0.0:8080
# IPv6 support
python manage.py runserver [::1]:8000
Advanced Options:
# Disable auto-reload
python manage.py runserver --noreload
# Use threading (default in Django 4.2+)
python manage.py runserver --nothreading
# Skip system checks
python manage.py runserver --skip-checks
# Force color output
python manage.py runserver --force-color
# Specify settings module
python manage.py runserver --settings=myproject.settings.development
Settings for Development Server:
# settings/development.py
# Debug mode (required for development server features)
DEBUG = True
# Allowed hosts (important for network access)
ALLOWED_HOSTS = [
'localhost',
'127.0.0.1',
'0.0.0.0',
'.ngrok.io', # For tunneling services
'192.168.1.100', # Your local network IP
]
# Internal IPs (for debug toolbar and other dev tools)
INTERNAL_IPS = [
'127.0.0.1',
'localhost',
'192.168.1.100',
]
# Development server settings
USE_TZ = True
TIME_ZONE = 'UTC'
# Static files (served by development server)
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
# Media files (served by development server)
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
Django's development server automatically restarts when it detects changes to Python files:
# The StatReloader watches for changes in:
# - Python files (.py)
# - Translation files (.po, .mo)
# - Template files (when DEBUG=True)
# Files that trigger reload:
# - models.py
# - views.py
# - urls.py
# - settings.py
# - forms.py
# - admin.py
# Files that DON'T trigger reload:
# - Static files (CSS, JS, images)
# - Media files
# - Log files
# - Database files
Customizing File Watching:
# settings/development.py
# Disable auto-reload for specific patterns
import sys
if 'runserver' in sys.argv:
# Custom reloader configuration
USE_I18N = True # Watch translation files
USE_L10N = True # Watch locale files
Manual Reload Triggers:
# Force reload by touching a Python file
touch manage.py
# Or modify any watched file
echo "# Force reload" >> myapp/models.py
Common Auto-Reload Problems:
# Problem: Server doesn't reload after changes
# Solution: Check file permissions and paths
# Problem: Too many reloads
# Solution: Exclude problematic directories
import os
from django.utils.autoreload import autoreload_started
def ignore_certain_files(sender, **kwargs):
"""Ignore files that shouldn't trigger reloads."""
import django.utils.autoreload
django.utils.autoreload.FILE_MODIFIED.disconnect(
dispatch_uid='django.utils.autoreload.file_modified'
)
if DEBUG:
autoreload_started.connect(ignore_certain_files)
Automatic Static File Serving:
# settings/development.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
# Django automatically serves static files when DEBUG=True
# URLs like /static/css/main.css are handled automatically
Manual Static File Configuration:
# urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# Your URL patterns
]
# Serve static files during development
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Media File Handling:
# models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(upload_to='avatars/')
document = models.FileField(upload_to='documents/')
# The development server will serve these files automatically
# URLs: /media/avatars/user1.jpg, /media/documents/doc.pdf
Custom Media Serving:
# views.py (for protected media files)
from django.http import FileResponse, Http404
from django.contrib.auth.decorators import login_required
import os
@login_required
def serve_protected_media(request, file_path):
"""Serve protected media files in development."""
if not settings.DEBUG:
raise Http404("Not found")
file_full_path = os.path.join(settings.MEDIA_ROOT, file_path)
if not os.path.exists(file_full_path):
raise Http404("File not found")
return FileResponse(open(file_full_path, 'rb'))
# urls.py
urlpatterns = [
path('protected-media/<path:file_path>/', views.serve_protected_media),
]
Installation:
pip install django-extensions
Configuration:
# settings/development.py
INSTALLED_APPS += [
'django_extensions',
]
Enhanced Server Features:
# Start enhanced development server
python manage.py runserver_plus
# Features:
# - Werkzeug debugger
# - Interactive error pages
# - Better error formatting
# - Request profiling
# With SSL support
python manage.py runserver_plus --cert-file cert.pem --key-file key.pem
# With specific reloader
python manage.py runserver_plus --reloader-type stat
Django Browser Reload:
pip install django-browser-reload
# settings/development.py
INSTALLED_APPS += [
'django_browser_reload',
]
MIDDLEWARE += [
'django_browser_reload.middleware.BrowserReloadMiddleware',
]
Template Integration:
<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
<title>My Django App</title>
{% load static %}
{% if debug %}
{% load django_browser_reload %}
{% browser_reload_script %}
{% endif %}
</head>
<body>
<!-- Your content -->
</body>
</html>
Using Browser-Sync:
# Install browser-sync
npm install -g browser-sync
# Start Django server
python manage.py runserver 8000
# Start browser-sync proxy
browser-sync start --proxy "localhost:8000" --files "**/*.py,**/*.html,**/*.css,**/*.js"
Using Gulp for Asset Watching:
// gulpfile.js
const gulp = require('gulp');
const browserSync = require('browser-sync').create();
gulp.task('serve', function() {
browserSync.init({
proxy: "localhost:8000",
files: [
"**/*.py",
"templates/**/*.html",
"static/**/*.css",
"static/**/*.js"
]
});
});
gulp.task('default', ['serve']);
Optimizing for Development:
# settings/development.py
# Database optimization for development
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
'OPTIONS': {
'timeout': 20,
}
}
}
# Disable unnecessary middleware in development
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Remove clickjacking protection in development
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# Optimize template loading
TEMPLATES[0]['OPTIONS']['debug'] = True
TEMPLATES[0]['OPTIONS']['string_if_invalid'] = 'INVALID_VARIABLE'
# Disable logging for better performance
LOGGING_CONFIG = None
Memory Usage Optimization:
# settings/development.py
# Reduce memory usage for large datasets
DATA_UPLOAD_MAX_MEMORY_SIZE = 2621440 # 2.5MB
FILE_UPLOAD_MAX_MEMORY_SIZE = 2621440 # 2.5MB
# Use dummy cache to avoid memory buildup
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
}
# Optimize session handling
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_AGE = 3600 # 1 hour
Using Django Silk:
pip install django-silk
# settings/development.py
INSTALLED_APPS += [
'silk',
]
MIDDLEWARE += [
'silk.middleware.SilkyMiddleware',
]
# Silk configuration
SILKY_PYTHON_PROFILER = True
SILKY_PYTHON_PROFILER_BINARY = True
SILKY_AUTHENTICATION = True
SILKY_AUTHORISATION = True
Access Profiling:
# Start server
python manage.py runserver
# Visit your application, then check profiling at:
# http://localhost:8000/silk/
Installation and Setup:
pip install django-debug-toolbar
# settings/development.py
INSTALLED_APPS += [
'debug_toolbar',
]
MIDDLEWARE += [
'debug_toolbar.middleware.DebugToolbarMiddleware',
]
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': lambda request: True,
'SHOW_COLLAPSED': True,
'INTERCEPT_REDIRECTS': False,
}
INTERNAL_IPS = [
'127.0.0.1',
'localhost',
]
URL Configuration:
# urls.py
from django.conf import settings
if settings.DEBUG:
import debug_toolbar
urlpatterns = [
path('__debug__/', include(debug_toolbar.urls)),
] + urlpatterns
Request Logging Middleware:
# middleware.py
import time
import logging
logger = logging.getLogger(__name__)
class DevelopmentLoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.time()
# Log request
logger.info(f"Request: {request.method} {request.path}")
response = self.get_response(request)
# Log response
duration = time.time() - start_time
logger.info(f"Response: {response.status_code} ({duration:.2f}s)")
return response
Error Handling Middleware:
# middleware.py
from django.http import JsonResponse
from django.conf import settings
import traceback
class DevelopmentErrorMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
try:
response = self.get_response(request)
except Exception as e:
if settings.DEBUG:
# Return detailed error information in development
error_data = {
'error': str(e),
'type': type(e).__name__,
'traceback': traceback.format_exc(),
}
return JsonResponse(error_data, status=500)
raise
return response
Local Network Access:
# Find your local IP address
# Linux/macOS:
ip addr show | grep inet
# or
ifconfig | grep inet
# Windows:
ipconfig
# Start server on all interfaces
python manage.py runserver 0.0.0.0:8000
# Access from other devices:
# http://192.168.1.100:8000 (replace with your IP)
Firewall Configuration:
# Linux (ufw)
sudo ufw allow 8000
# macOS (built-in firewall)
# System Preferences > Security & Privacy > Firewall > Options
# Allow incoming connections for Python
# Windows
# Windows Defender Firewall > Allow an app through firewall
# Add Python to allowed apps
Using ngrok:
# Install ngrok
# Download from https://ngrok.com/
# Start Django server
python manage.py runserver 8000
# In another terminal, start ngrok
ngrok http 8000
# Access your app via public URL:
# https://abc123.ngrok.io
Using localtunnel:
# Install localtunnel
npm install -g localtunnel
# Start Django server
python manage.py runserver 8000
# Create tunnel
lt --port 8000 --subdomain myapp
# Access via: https://myapp.loca.lt
Using Django Extensions:
# Generate self-signed certificate
python manage.py generate_secret_key > .secret_key
# Create certificate files
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
# Start HTTPS server
python manage.py runserver_plus --cert-file cert.pem --key-file key.pem
Using mkcert for Trusted Certificates:
# Install mkcert
# macOS: brew install mkcert
# Linux: Follow instructions at https://github.com/FiloSottile/mkcert
# Create local CA
mkcert -install
# Generate certificate for localhost
mkcert localhost 127.0.0.1 ::1
# Start server with certificate
python manage.py runserver_plus --cert-file localhost+2.pem --key-file localhost+2-key.pem
Problem: Error: That port is already in use.
Solutions:
# Find process using port 8000
lsof -ti:8000 # macOS/Linux
netstat -ano | findstr :8000 # Windows
# Kill process
kill -9 $(lsof -ti:8000) # macOS/Linux
taskkill /PID <PID> /F # Windows
# Use different port
python manage.py runserver 8080
Problem: Permission denied when starting server
Solutions:
# Check port permissions (ports < 1024 require root)
python manage.py runserver 8000 # Use port > 1024
# Check file permissions
chmod +x manage.py
# Check virtual environment activation
which python # Should point to venv
Problem: CSS/JS files return 404 errors
Solutions:
# Ensure DEBUG=True in settings
DEBUG = True
# Check STATIC_URL setting
STATIC_URL = '/static/'
# Verify STATICFILES_DIRS
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
# Add static file serving to URLs
from django.conf.urls.static import static
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Problem: Server fails to start with various errors
Diagnostic Steps:
# Check Django installation
python -c "import django; print(django.get_version())"
# Validate settings
python manage.py check
# Check database connectivity
python manage.py dbshell
# Verify migrations
python manage.py showmigrations
# Check for syntax errors
python -m py_compile manage.py
Development Server:
Production Server (Gunicorn/uWSGI):
Testing Production-like Setup:
# Install production server
pip install gunicorn
# Test with Gunicorn
gunicorn myproject.wsgi:application --bind 127.0.0.1:8000
# Test static file serving
python manage.py collectstatic
Production Readiness Checklist:
# settings/production.py
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com']
SECURE_SSL_REDIRECT = True
STATIC_ROOT = '/var/www/static/'
MEDIA_ROOT = '/var/www/media/'
# Use production database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
# ... production database config
}
}
The Django development server is a powerful tool for rapid development and testing. Understanding its features, limitations, and optimization techniques ensures a productive development experience while preparing for smooth production deployment.
Managing Django Environments: Local, Staging, and Production
Proper environment management is crucial for Django applications. This comprehensive guide covers setting up and managing different environments, ensuring smooth transitions from development to production while maintaining security and performance.
Working with Django Shell
The Django shell is an interactive Python environment with your Django project's context loaded. It's an essential tool for development, debugging, testing, and data manipulation. This comprehensive guide covers everything you need to know about using Django's shell effectively.