Packaging for production — Deploying to Railway
In this chapter, you will learn how to configure the production environment, deploy the Django blog application to Railway, and obtain a public access link.
Production environment configuration
In the development environment, DEBUG=True, and Django displays detailed error information and debug pages.
In the production environment, DEBUG must be turned off, and security options must be configured correctly.
settings.py production configuration
Example
import os
# Read the secret key from an environment variable (do not hardcode it in code)
SECRET_KEY = os.environ.get('SECRET_KEY', 'Development environment default secret key')
# DEBUG is controlled via environment variables.
DEBUG = os.environ.get('DEBUG', 'True').lower() == 'true'
# Allowed hostnames
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '127.0.0.1,localhost').split(',')
# Static file collection directory
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # staticfiles/ in the project root directory
STATIC_URL = '/static/'
SECRET_KEYIt is Django's most important security key, used to encrypt sessions, CSRF tokens, etc. It must never be hardcoded in code or committed to Git. In the production environment, it is injected via environment variables.
Dependency Management and requirements.txt
Generate a dependency list; the deployment platform uses it to install the packages required by the project.
(venv) $ pip freeze > requirements.txt
Check the file contents to ensure the following key dependencies are included:
Django>=5.0,<6.0 gunicorn>=21.0 # 生产级 WSGI 服务器 whitenoise>=6.0 # 静态文件服务(可选)
If gunicorn is not present, install it first:
(venv) $ pip install gunicorn (venv) $ pip freeze > requirements.txt
Configure Gunicorn + Whitenoise
Django's built-inrunserverNot suitable for production environment.
GunicornIt is a Python production-grade WSGI server that handles concurrent requests.
WhitenoiseAllow Gunicorn to directly serve static files (CSS, JS, images).
Example
# The Whitenoise middleware must be placed after SecurityMiddleware and before other middleware.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # Add: static file middleware
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Create in the project root directoryProcfiletelling Railway how to start the application:
web: gunicorn blog_project.wsgi --log-file -
Collect static files
In the production environment, Django does not automatically serve static files; you need to usecollectstaticCollect into a unified directory.
(venv) $ python manage.py collectstatic
This command will copy the static files of the Admin backend and the blog app toSTATIC_ROOTDirectory (staticfiles/).
In a development environment, you generally don't need to run collectstatic (Django automatically finds each app's static directory). However, it must be run before deployment to ensure all static files are consolidated into one directory for the web server to use.
Push the project to GitHub
Create .gitignore
Ensure sensitive files and temporary files are not committed:
venv/ __pycache__/ *.pyc db.sqlite3 staticfiles/ .env
Push to GitHub
$ git init $ git add . $ git commit -m "初始化 Django 博客项目" $ git branch -M main $ git remote add origin https://github.com/你的用户名/django-blog.git $ git push -u origin main
Railway Deployment
RailwayIt is an emerging cloud deployment platform with good support for full-stack applications such as Django.
Deployment steps
- Visitrailway.app, log in with GitHub account
- Click "New Project" → "Deploy from GitHub repo" → Select django-blog 仓library
- Railway automatically detects the Procfile and recognizes the start command.
- Set environment variables in Variables.
- Click Deploy and wait for the build and deployment to complete.
Environment variable configuration
| Variable Name | Value | Description |
|---|---|---|
| SECRET_KEY | Randomly generated long string | Django security key |
| DEBUG | False | Disable debug mode |
| ALLOWED_HOSTS | .railway.app | Allow access from the Railway domain. |
Quickly generate SECRET_KEY:
$ python -c "import secrets; print(secrets.token_urlsafe(50))"
After successful deployment, you will get a link like:https://django-blog.up.railway.app
Railway's free tier is limited ($5 per month or 500 hours). If you're just testing or learning, remember to pause the project after using it up. Heroku has canceled its free plan, so this tutorial recommends Railway as an alternative.
Next learning direction
| Learning Direction | Who It's For | Recommended Starting Point |
|---|---|---|
| Django REST Framework (DRF) | Need to build an API backend for front-end frameworks (Vue3/React). | Learn Serializer + ViewSet to turn the blog into an API service |
| PostgreSQL | A production-grade database is needed | Replace SQLite and use django-environ to manage database configuration |
| Celery Async Task | Need background tasks (sending emails, generating reports). | Integrate Redis + Celery to implement an asynchronous task queue. |
| Django + Vue3/React frontend-backend separation | Want a front-end/back-end separated architecture | Build the API backend with DRF, build the frontend with Vue3/React, and communicate via fetch |
Chapter summary
In 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 one-click deployment on Railway.
other extensions