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

# File path: blog_project/settings.py
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

# File path: blog_project/settings.py

# 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

  1. Visitrailway.app, log in with GitHub account
  2. Click "New Project" → "Deploy from GitHub repo" → Select django-blog 仓library
  3. Railway automatically detects the Procfile and recognizes the start command.
  4. Set environment variables in Variables.
  5. Click Deploy and wait for the build and deployment to complete.

Environment variable configuration

Variable NameValueDescription
SECRET_KEYRandomly generated long stringDjango security key
DEBUGFalseDisable debug mode
ALLOWED_HOSTS.railway.appAllow 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 DirectionWho It's ForRecommended 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
PostgreSQLA production-grade database is neededReplace SQLite and use django-environ to manage database configuration
Celery Async TaskNeed background tasks (sending emails, generating reports).Integrate Redis + Celery to implement an asynchronous task queue.
Django + Vue3/React frontend-backend separationWant a front-end/back-end separated architectureBuild 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