Chapter 10

部署与工程化

把项目从 runserver 送上生产:分环境配置、静态收集、gunicorn + nginx、缓存、Docker,最后一份上线 checklist。

10.1 生产与开发的分野

runserver 只是开发服务器,绝不能用于生产。生产需要 WSGI/ASGI 服务器(gunicorn/uvicorn)跑应用、nginx 做反向代理与静态服务、独立数据库、关闭 DEBUG。

分环境配置(Settings Split)
把 settings 拆成 base/dev/prod,用环境变量注入密钥与开关,避免把生产敏感信息写进代码库。
collectstatic
把各 App 与 STATICFILES_DIRS 的静态文件收集到 STATIC_ROOT 单一目录,交给 nginx/CDN 服务。
WSGI 服务器(gunicorn)
生产级 Python 应用服务器,多进程/多线程跑 Django,替代 runserver。异步项目用 uvicorn(ASGI)。
反向代理(nginx)
处理 TLS、静态文件、负载均衡,把动态请求转发给 gunicorn,是生产标准前置。
缓存(Cache)
用 Redis/Memcached 缓存视图、片段或查询结果,降低数据库压力、提升响应速度。
Docker
把应用及依赖打包成镜像,实现「一次构建处处运行」,配 docker-compose 编排 web/db/redis/nginx。
check --deploy
Django 内置的部署体检命令,扫描 DEBUG、SECRET_KEY、HTTPS、Cookie 安全等常见隐患。

10.2 分环境的 settings

# settings/prod.py
import os
from .base import *

DEBUG = False
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]     # 从环境变量读
ALLOWED_HOSTS = ["www.gufacode.com"]

SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000
$ export DJANGO_SETTINGS_MODULE=mysite.settings.prod
三条铁律

生产必须 DEBUG=False(否则报错页泄露源码)、SECRET_KEY 走环境变量(绝不入库)、ALLOWED_HOSTS 精确设定(防 Host 头攻击)。三者任一疏漏都是严重安全事故。

10.3 生产数据库

# 生产用 PostgreSQL,凭据走环境变量
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.get("DB_HOST", "db"),
        "PORT": "5432",
        "CONN_MAX_AGE": 60,      # 持久连接
    }
}

10.4 静态文件与 WhiteNoise

$ python manage.py collectstatic --noinput

# 若不想单独配 nginx 静态,可用 WhiteNoise 让 Django 直接高效服务静态
$ pip install whitenoise

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",   # 紧随其后
    ...
]
STORAGES = {"staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"}}

10.5 gunicorn + nginx

# 启动 gunicorn(4 个 worker)
$ gunicorn mysite.wsgi:application --bind 0.0.0.0:8000 --workers 4
# nginx 反向代理片段
server {
    listen 80;
    server_name www.gufacode.com;

    location /static/ { alias /app/staticfiles/; }
    location /media/  { alias /app/media/; }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

10.6 缓存

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": "redis://redis:6379/1",
    }
}

# 视图级缓存 15 分钟
from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def post_list(request): ...

10.7 Docker 化

# Dockerfile
FROM python:3.12-slim
ENV PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
RUN python manage.py collectstatic --noinput
CMD ["gunicorn", "mysite.wsgi", "--bind", "0.0.0.0:8000", "--workers", "4"]
# docker-compose.yml(要点)
services:
  web:
    build: .
    env_file: .env
    depends_on: [db, redis]
  db:
    image: postgres:16
  redis:
    image: redis:7

10.8 部署前 checklist

$ python manage.py check --deploy   # 自动体检
全书回顾

你已走完 Django 的完整链路:项目搭建 → 路由 → ORM → 视图 → 模板 → 表单 → Admin → 认证 → DRF → 部署。Django 的哲学始终如一——「自带电池、DRY、为有截止日期的完美主义者」。愿你用它又快又稳地交付。

10.9 结语