Properly configuring Django for production is critical for security and performance.
Settings Structure
myproject/
├── settings/
│ ├── __init__.py
│ ├── base.py # Shared settings
│ ├── development.py
│ └── production.py
python# settings/base.py from pathlib import Path import os BASE_DIR = Path(__file__).resolve().parent.parent.parent INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # Your apps 'blog', 'accounts', ] # ... other shared settings
python# settings/production.py from .base import * import os DEBUG = False SECRET_KEY = os.environ['DJANGO_SECRET_KEY'] ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',') # Database DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ['DB_NAME'], 'USER': os.environ['DB_USER'], 'PASSWORD': os.environ['DB_PASSWORD'], 'HOST': os.environ['DB_HOST'], 'PORT': os.environ.get('DB_PORT', '5432'), 'CONN_MAX_AGE': 60, 'OPTIONS': { 'sslmode': 'require', }, } } # Security settings SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_BROWSER_XSS_FILTER = True SECURE_CONTENT_TYPE_NOSNIFF = True SECURE_HSTS_SECONDS = 31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True # Static files STATIC_ROOT = BASE_DIR / 'staticfiles' STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' # Logging LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '{levelname} {asctime} {module} {message}', 'style': '{', }, }, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'formatter': 'verbose', }, }, 'root': { 'handlers': ['console'], 'level': 'INFO', }, 'loggers': { 'django': { 'handlers': ['console'], 'level': 'INFO', 'propagate': False, }, }, } # Email EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = os.environ.get('EMAIL_HOST', 'smtp.sendgrid.net') EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER') EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
Environment Variables
python# Using python-dotenv # pip install python-dotenv # settings/base.py from dotenv import load_dotenv load_dotenv() # Or using django-environ # pip install django-environ import environ env = environ.Env( DEBUG=(bool, False), ALLOWED_HOSTS=(list, []), ) DEBUG = env('DEBUG') SECRET_KEY = env('SECRET_KEY') DATABASES = {'default': env.db()}
bash# .env file (never commit this!) DJANGO_SECRET_KEY=your-super-secret-key-here DEBUG=False ALLOWED_HOSTS=example.com,www.example.com DATABASE_URL=postgres://user:pass@host:5432/dbname
Pre-Deployment Checklist
bash# Run deployment check python manage.py check --deploy # Example output: # System check identified some issues: # WARNINGS: # ?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. # ?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True.
python# Addressing common warnings # 1. SECURE_SSL_REDIRECT - Redirect HTTP to HTTPS SECURE_SSL_REDIRECT = True # 2. SECURE_HSTS_SECONDS - HTTP Strict Transport Security SECURE_HSTS_SECONDS = 31536000 # 1 year # 3. SESSION_COOKIE_SECURE - Send cookies only over HTTPS SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True # 4. X-Frame-Options X_FRAME_OPTIONS = 'DENY' # 5. Secret key must be set and unique # Never use the default or commit to version control