【Web应用开发笔记】Django笔记9:Django部署注意事项补充

前言

在前面的博客中,我在本地以及在 pythonanywhere 都部署过简单的 web 网站。

本文将做一些梳理、补充。

1. 关于"架构"

部署过程实际上取决于你使用的"技术选型" & "平台类型"。

1.1 理论架构

以 Django 为后端的 web 服务的"理论架构"就是:

  • web 服务器
  • WSGI/ASGI
  • web 应用

1.2 标准部署架构

传统上,严格遵守上述理论框架的部署架构就是

  • web 服务器:Nginx
  • WSGI:Gunicorn
  • web 应用:Django

简单记为:Nginx + WSGI +Django

这套架构的优势来自于 Nginx 作为专业 web服务 带来的性能优势。

这套架构对于初学者来说的缺点在于需要额外的 Nginx 相关知识。

在部署方面,常依托于 IaaS 平台。

1.3 便捷部署架构

作为初学者,比较常用的架构是

  • web 服务器(功能分散在以下地方)
    • PaaS 平台:边缘处理 TLS/安全
    • Gunicorn:处理 HTTP 解析
    • WhiteNoise:处理静态文件
  • WSGI 服务:Gunicorn
  • web 应用:Django

简单记为:Gunicorn + WhiteNoise + Django

这套架构的优势来自于无需额外的 web 服务器相关知识,专注于项目代码。

这套架构的缺点在于,如果业务发展到大规模并发的阶段,可能会有性能问题。

  • WhiteNoise 的瓶颈:高并发静态文件请求会占用 Django 工作进程(因为 WhiteNoise 是 WSGI 中间件,文件读取是同步阻塞的)
  • Gunicorn 的瓶颈:没有 Nginx 的 keep-alive 连接池、缓存、压缩等优化
  • 但注意:对于小到中型项目,这个瓶颈通常在数据库或业务逻辑,不在静态文件服务。

在部署方面,常依托于 PaaS 平台。

  • 注1:

    • 实际上,大多数 PaaS 平台在边缘仍有反向代理(如 Nginx),但这对你透明。
    • 当然,WhiteNoise 仍是需要的,处理的是应用层静态文件服务。
  • 注2:

    • 这里将 Gunicorn、WhiteNoise 放在 "web 服务器" 下,只是为了便于初学者理解功能上的对应关系。
    • 实际上:
      • Gunicorn 属于 WSGI 层(标准架构中的中间层),并非 Web 服务器。
      • WhiteNoise 是嵌入 Django 的中间件,让应用层具备了服务静态文件的能力------这在严格的三层理论架构中是不存在的,属于"便捷架构"的特例。
      • 因此,"Gunicorn + WhiteNoise + Django" 本质上是用 PaaS 提供的边缘网关 替代了 Nginx 的 Web 服务器角色,同时用 WhiteNoise 弥补了缺少 Nginx 后静态文件服务的空白。

2. 关于数据库

2.1 为什么需要 托管数据库服务

在本地进行学习过程中,我使用过 SQLite、PostgreSQL。

然而在实际部署过程中,或者说在最终需要上线的时候,我们需要 购买/使用托管数据库服务。

实际生产环境中,不应该把数据库和 Django 塞在同一台机器里,更不该用 SQLite。

场景 存储要求 风险
SQLite 几十MB到几GB 文件损坏=数据丢失,无备份机制
自建 PostgreSQL 需要专业 DBA 知识,磁盘要备份、监控、扩容 磁盘满=服务崩,误删=数据永久丢失
托管数据库服务 自动备份、自动扩容、自动故障转移 贵一点,但 sleep well

因此,需要把 "托管数据库服务" 作为我们成本的一部分!

2.2 什么时候开始用 托管数据库服务

  • 基本流程

    首先,在本地开发的过程中,我们仍使用本地数据库。

    在本地功能验证完毕,准备部署之前,我们需要购买并验证托管数据库服务。

    然后再部署到生产环境。

  • 要点

    本地验证的一个注意点是:本地测试与生产环境隔离

    即:不要让本地调试、测试代码造成的改动污染生产环境数据库

  • 本地验证 托管数据库服务 的策略

    策略1:本地临时连接,仅验证连通性,不验证业务逻辑,验证后立即断开

    策略2:创建临时测试库,本地连接并验证连通性和业务逻辑,部署时改回生产库

3. 部署(以 PaaS 平台为例)

这里我仅讨论 Gunicorn + WhiteNoise + Django 这套框架下的部署。

3.1 环境变量 & 相关代码

  • 我们的思路是:
    • 将部署时需要修改的配置专门放在一个配置文件中
  • .env 文件
    • 在项目根目录下
    • 请勿将生产环境的密码、密钥上库到 github
bash 复制代码
DATABASE_URL=postgres://用户名:密码@localhost:5432/数据库名
DEBUG=False
SECRET_KEY=xxx
ALLOWED_HOSTS=abc.com
CSRF_TRUSTED_ORIGINS=http://abc.com
  • settings.py
    • 这里的代码通过读取环境变量获取相应的值
python 复制代码
from environs import Env # new

env = Env() # new
env.read_env() # new

...

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env.str("SECRET_KEY")

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env.bool("DEBUG", default=False)

ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=["localhost", "127.0.0.1"])

...

DB_URL_STR = env.str("DATABASE_URL", default="")
if "sqlite3" in DB_URL_STR:
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": BASE_DIR / "db.sqlite3",
        }
    }

else:
    DATABASES = {
        "default": env.dj_db_url("DATABASE_URL"),
    }

...

CSRF_TRUSTED_ORIGINS = env.list(
    "CSRF_TRUSTED_ORIGINS", 
    default=["http://localhost", "http://127.0.0.1"]
)
  • 解析
    • SECRET_KEY 和 DATABASES 我们不给默认值

      • 防止相关密码、密钥 泄露
      • 如果不配置就报错,防止在生产环境产生默认行为
    • ALLOWED_HOSTS、CSRF_TRUSTED_ORIGINS

      • ALLOWED_HOSTS 防 Host 头攻击
      • CSRF_TRUSTED_ORIGINS 防跨站伪造
    • 本地开发阶段

      • 可以使用 DATABASE_URL=sqlite3,在代码里面会走到本地数据库的配置分支
      • DEBUG=True,有助于看到报错信息
      • ALLOWED_HOSTS、CSRF_TRUSTED_ORIGINS
        • 用 # 注释掉
        • 或者进行如下配置
      bash 复制代码
      ALLOWED_HOSTS=localhost,127.0.0.1
      CSRF_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1
      • 这样会准许 localhost 的访问
    • 部署阶段

      • DATABASE_URL 请使用专门的 托管数据库服务 厂商所提供的相关配置
      • DEBUG=False
      • SECRET_KEY 通过以下命令生成
      python 复制代码
      python -c "import secrets; print(secrets.token_urlsafe())"
      • ALLOWED_HOSTS、CSRF_TRUSTED_ORIGINS 根据 PaaS 平台提供的 URL 进行配置

3.2 部署过程

  • 部署过程(在 PaaS 平台的终端 或者 前端)
    • step 1: 更新代码(git clone)
    • step 2: 导入依赖(按照 requirements.txt)
    • step 3: 配置 .env 文件(五个参数)
    • step 4: 数据库相关操作(migrate、createsuperuser)
    • step 5: 静态文件(collectstatic)
    • step 6: 重启服务
    • step 7: 测试 & 问题修复
  • 注意点:
    • step 1: 更新代码(git clone)

      • 可能需要在平台做 SSH 相关配置
    • step 2: 导入依赖(按照 requirements.txt)

      • 注意使用哪个 python(比如在PaaS平台选择环境时,可能会选择 python版本,那么在终端操作就需要找对 python)
      bash 复制代码
      # 形如
      python3.11 -m pip install -r requirements.txt
      • 这里的 python3.11 是我学习过程中使用,并在 PaaS 平台选择的
        • 实际需要根据部署时的实际情况进行选择(形如:python、python3.12等)
        • 你可以使用形如 which python3.11 的命令来查看需要的 python 版本是否存在
    • step 3: 配置 .env 文件(五个参数)

      • 如前面的 3.1 节所述
    • step 4: 数据库相关操作(migrate、createsuperuser)

      • 注意要使用托管数据库服务
      • 以及专门为生产环境创建的数据库
      • 由于我们使用的数据库与生产环境不是同一个
        • 需要依次执行 migrate、createsuperuser
      bash 复制代码
      # 刷新数据库
      python3.11 manage.py makemigrations posts
      python3.11 manage.py migrate
      
      # 创建管理员
      python3.11 manage.py createsuperuser
    • step 5: 静态文件(collectstatic)

      • 执行 collectstatic 自动收集静态文件
      bash 复制代码
      python3.11 manage.py collectstatic
      • 注:由于 staticfiles/ 可以由这个命令自动生成,故此我在 git 上库中将其忽略,所以在部署时需要执行 collectstatic 来生成这个文件夹
    • step 6: 重启服务

    • step 7: 测试 & 问题修复

      • 功能测试
      • 进行静态文件访问 <主页URL>/static/admin/css/base.css
  • 补充
    • 有些平台可能在前端配置的时候就可以配环境变量

3.3 依赖

  • python
    • requirements.txt 很重要,在进行了导入包的操作后需要进行更新
    • 目前导入过的包如下:
bash 复制代码
pip install django~=4.2.0 # Django
pip install black # 代码格式化工具,开发用,保持统一代码风格
pip install "environs[django]" # 用于读取环境变量
pip install gunicorn==20.1.0 # WSGI
pip install "psycopg[binary]"==3.1.8 # 访问 PostgreSQL 数据库,注意:不同类型数据库用的驱动包不一样!
pip install whitenoise==6.12.0 # WhiteNoise 中间件
相关推荐
pl4H522a63 分钟前
Python 高效实现 Excel 转 TXT 文本
java·python·excel
稻草猫.8 分钟前
Spring事务操作全解析
java·数据库·后端·spring
数据知道11 分钟前
claw-code 源码详细分析:Compaction 前置课——上下文压缩在接口层要预留哪些旋钮,避免后期全局返工?
python·ai·claude code
小邓睡不饱耶17 分钟前
花店花品信息管理系统开发实战:Python实现简易门店管理系统
服务器·python·microsoft
witAI40 分钟前
手机生成剧本杀软件2025推荐,创新剧情设计工具助力创作
人工智能·python
greatofdream1 小时前
LLVM安装使用
笔记·mlir
希望永不加班1 小时前
SpringBoot 整合 MongoDB
java·spring boot·后端·mongodb·spring
派大星~课堂1 小时前
【力扣-138. 随机链表的复制 ✨】Python笔记
python·leetcode·链表
王忘杰1 小时前
0基础CUDA炼丹、增加断点保存,从零开始训练自己的AI大模型 87owo/EasyGPT Python CUDA
开发语言·人工智能·python
数据知道1 小时前
claw-code 源码详细分析:`reference_data` JSON 快照——大型移植里「对照底稿」该怎么治理与演进?
linux·python·ubuntu·json·claude code