Bundle and Deploy β Deploy to Railway |
\n\nIn this chapter, you will learn how to configure a production environment and deploy your Django blog application to Railway, obtaining a publicly accessible link.
\n\n\n\n
Production Environment Configuration
\n\nIn the development environment, DEBUG=True, and Django displays detailed error messages and the debug page.
In production, DEBUG must be disabled, and security settings must be configured correctly.
Production Configuration in settings.py
\n\nExample
\n\n# File path: blog_project/settings.py\n\nimport os\n\n# Security key is read from environment variable (do NOT hardcode in code)\nSECRET_KEY = os.environ.get('SECRET_KEY', 'Default Secret Key for Development Environment')\n\n# DEBUG is controlled via environment variable\nDEBUG = os.environ.get('DEBUG', 'True').lower() == 'true'\n\n# Allowed hostnames\nALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '127.0.0.1,localhost').split(',')\n\n# Static files collection directory\nSTATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # staticfiles/ under project root\nSTATIC_URL = '/static/'\n\n\n\n\n\n\n
SECRET_KEYis Djangoβs most critical security key, used to encrypt sessions, CSRF tokens, etc. It must never be hardcoded in code or committed to Git. In production, inject it via environment variables.
\n\n
Dependency Management and requirements.txt
\n\nGenerate a dependency list; the deployment platform uses it to install required packages.
\n\n(venv) $ pip freeze > requirements.txt\n\n\nCheck the file contents to ensure it includes the following key dependencies:
\n\nDjango>=5.0,=21.0 # production-grade WSGI server\nwhitenoise>=6.0 # static file serving (optional)\n\n\nIf gunicorn is missing, install it first:
(venv) $ pip install gunicorn\n(venv) $ pip freeze > requirements.txt\n\n\n\n\n
Configure Gunicorn + Whitenoise
\n\nDjangoβs built-in runserver is unsuitable for production.
Gunicorn is a production-grade WSGI server for Python, handling concurrent requests.
\n\nWhitenoise enables Gunicorn to serve static files (CSS, JS, images) directly.
\n\nExample
\n\n# File path: blog_project/settings.py\n\n# Whitenoise middleware must be placed AFTER SecurityMiddleware and BEFORE other middleware\nMIDDLEWARE = [\n 'django.middleware.security.SecurityMiddleware',\n 'whitenoise.middleware.WhiteNoiseMiddleware', # New: static files middleware\n 'django.contrib.sessions.middleware.SessionMiddleware',\n 'django.middleware.common.CommonMiddleware',\n 'django.middleware.csrf.CsrfViewMiddleware',\n 'django.contrib.auth.middleware.AuthenticationMiddleware',\n 'django.contrib.messages.middleware.MessageMiddleware',\n 'django.middleware.clickjacking.XFrameOptionsMiddleware',\n]\n\n\nCreate a Procfile in the project root to tell Railway how to start the app:
web: gunicorn blog_project.wsgi --log-file -\n\n\n\n\n
Collect Static Files
\n\nIn production, Django does not serve static files automatically. Use collectstatic to gather them into a unified directory.
(venv) $ python manage.py collectstatic\n\n\nThis command copies static files from the admin backend and your blog app into the STATIC_ROOT directory (staticfiles/).
\n\n\nIn development, you usually donβt need to run
\ncollectstatic(Django automatically finds static files in each appβsstatic/directory). However, you must run it before deployment to ensure all static assets are centralized for the web server.
\n\n
Push Project to GitHub
\n\nCreate .gitignore
\n\nEnsure sensitive and temporary files are not committed:
\n\nvenv/\n__pycache__/*.pyc\ndb.sqlite3\nstaticfiles/\n.env\n\n\nPush to GitHub
\n\n$ git init\n$ git add .\n$ git commit -m "Initialize Django Blog Project"\n$ git branch -M main\n$ git remote add origin https://github.com/your-username/django-blog.git\n$ git push -u origin main\n\n\n\n\n
Railway Deployment
\n\nRailway is an emerging cloud deployment platform with strong support for full-stack apps like Django.
\n\nDeployment Steps
\n\n- \n
- Visit railway.app and log in with your GitHub account. \n
- Click "New Project" β "Deploy from GitHub repo" β select the
django-blogrepository. \n - Railway automatically detects the
Procfileand recognizes the startup command. \n - In the Variables section, set environment variables. \n
- Click Deploy and wait for the build and deployment to complete. \n
Environment Variable Configuration
\n\n| Variable Name | \nValue | \nDescription | \n
|---|---|---|
| SECRET_KEY | \nA randomly generated long string | \nDjango security key | \n
| DEBUG | \nFalse | \nDisable debug mode | \n
| ALLOWED_HOSTS | \n.railway.app | \nAllow access from Railway domains | \n
Quickly generate a SECRET_KEY:
$ python -c "import secrets; print(secrets.token_urlsafe(50))"\n\n\nAfter successful deployment, youβll get a link like: https://django-blog.up.railway.app
\n\n\nRailway has limited free tier (e.g., $5/month or 500 hours). If youβre only testing/learning, remember to pause the project after usage. Heroku has discontinued its free plan, so Railway is recommended in this tutorial as an alternative.
\n
\n\n
Next Learning Directions
\n\n| Learning Direction | \nWho Itβs For | \nRecommended Starting Point | \n
|---|---|---|
| Django REST Framework (DRF) | \nThose needing an API backend for frontend frameworks (Vue3/React) | \nLearn Serializer + ViewSet; convert the blog into an API service | \n
| PostgreSQL | \nThose needing a production-grade database | \nReplace SQLite; use django-environ to manage database configuration | \n
| Celery Async Tasks | \nThose needing background tasks (e.g., sending emails, generating reports) | \nIntegrate Redis + Celery to implement an async task queue | \n
| Django + Vue3/React (Frontend-Backend Separation) | \nThose wanting a frontend-backend decoupled architecture | \nUse DRF for the API backend, Vue3/React for the frontend, and communicate via fetch | \n
\n\n
Chapter Summary
\n\nIn this chapter, you completed the final step: configuring the production environment (SECRET_KEY/DEBUG/ALLOWED_HOSTS), generating requirements.txt, configuring Gunicorn + Procfile, pushing to GitHub, and deploying to Railway with one click.
YouTip