【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 中间件
相关推荐
所谓伊人,在水一方3332 小时前
【Python数据可视化精通】第1讲 | 数据可视化的本质与认知心理学基础
开发语言·python·信息可视化·matplotlib
小鸡脚来咯2 小时前
RESTful API 设计与后端服务开发面试题
后端·restful
所谓伊人,在水一方3332 小时前
【Python数据科学实战之路】第18章 | 大模型与数据科学:LLM赋能数据分析新时代
开发语言·python·深度学习·神经网络·数据分析·tensorflow
Assby2 小时前
Java开发者学习Go语言:Go开发和Java开发的一些区别
后端·go
吃吃喝喝小朋友2 小时前
Django Admin后台系统
后端·python·django
赵谨言2 小时前
摘要本研究旨在构建一套基于OpenCV与CNN融合技术的银行卡号自动识别系统,重点解决不同银行卡号字体格式差异、倾斜污损等复杂场景下的识别难题
大数据·开发语言·经验分享·python
树獭叔叔2 小时前
检索增强生成(RAG):让大模型突破知识边界
后端·aigc·openai
南囝coding2 小时前
OpenClaw 到底能干什么?可以看看这 60 个真实用例
前端·后端