章节目录:

〔一〕告别Excel困境——开发企业内部保卫系统,我为何死磕Windows环境下Django + Waitress + Nginx这套技术栈

📌写在最前面

🔔上一篇我们重点讲了Windows环境下Django+Waitress+Nginx技术选型,是系列文章第1篇,本文是企业Django系列第2篇,将手把手和大家从零开始在Windows上部署生产环境,涵盖Python安装、虚拟环境、Waitress、Nginx、SSL证书、静态文件配置等,共11个步骤,并解释每一步为什么要这么做——诠释原理,而不是机械地复制粘贴。

读完本文,你将能通过浏览器访问到自己部署的Django项目(HTTPS),并理解:

  • 在Windows上完成Django生产环境的完整部署(HTTPS访问)
  • 理解安装Python时勾选“Add to PATH”的作用、为什么要升级pip
  • 配置Nginx反向代理,解决登录状态丢失的问题
  • 生成自签名证书,让内网HTTPS正常使用

01 环境准备:选对操作系统和路径

我的生产环境选择:Windows Server 2016 ,开发环境在Win7\Windows 10也实测可用

项目 说明
操作系统 Windows Server(Win7\Windows 10实测同样适用)
项目路径 D:\JingFuWang(建议非C盘,便于备份和维护)
服务器IP 本文以 19.74.8.18 为例,请替换为你的实际IP

💡 为什么选Windows? 企业内网服务器普遍使用Windows Server,办公电脑也多为Windows桌面系统,IT人员熟悉图形界面,无需学习Linux命令,部署和维护成本最低。这是务实的选择,不是技术上的“将就”。

📌重点是:这套技术栈虽然部署在Windows上,但并没有与Windows平台强绑定。Django本身就是跨平台的,Waitress只在生产环境中作为WSGI服务器使用,应用代码完全不依赖Windows特有API。Nginx的配置在Linux下几乎完全相同,仅需调整路径斜杠方向。这意味着,如果未来企业将服务器迁移至Linux环境,当前系统可以低成本、几乎零修改地完成移植——只需更换WSGI服务器(Waitress → Gunicorn)并调整Nginx配置路径即可。这种可移植性,既保护了企业的技术投资,也为未来架构演进保留了灵活性。

🔔 提示:本章所有命令均在“命令提示符(cmd)”中执行,建议以管理员身份运行(右键→以管理员身份运行),避免权限问题。

02 安装Python 3.8.10(关键:PATH勾选)

2.1 下载安装包

访问 python.org/downloads/,选择 Python 3.8.10 的Windows x86-64 executable installer。

2.2 运行安装程序(这一步决定成败)

双击安装包,务必注意以下两点:

┌─────────────────────────────────────────────────────────┐
│ Install Python 3.8.10 (64-bit)                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ☑ Install Now                                          │
│     C:\Users\xxx\AppData\Local\Programs\Python\Python38 │
│                                                         │
│  ☐ Customize installation                               │
│                                                         │
│  ☑ Add Python to PATH     ← ← ← 必须勾选!              │
│                                                         │
│                      [ Cancel ]  [ Next > ]             │
└─────────────────────────────────────────────────────────┘
  1. 勾选 “Add Python to PATH”
    · 为什么必须勾选?
    PATH是Windows的环境变量,系统根据PATH中的路径去查找可执行程序。如果不勾选,你在其它路径命令行中输入 python 会提示“不是内部或外部命令”。勾选后,安装程序会自动把Python的安装目录和Scripts目录加入PATH,后续的 python、pip 命令才能正常使用。
    · 如果忘了勾选怎么办? 重新运行安装程序,选择“Modify”并勾选该选项即可。
  2. 选择 Customize installation(自定义安装),以便手动设置安装路径。

在高级选项中,推荐勾选:

┌─────────────────────────────────────────────────────────┐
│ Advanced Options                                        │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ☑ Install for all users                               │
│  ☑ Associate files with Python                         │
│  ☑ Create shortcuts for installed applications         │
│  ☑ Add Python to environment variables                 │
│                                                         │
│  ☐ Precompile standard library                         │
│  ☐ Download debugging symbols                          │
│  ☐ Download debug binaries                             │
│                                                         │
│  Customize install location:                            │
│  [D:\Python38 ]                                         │
│                                                         │
│                      [ Back ]  [ Install ]              │
└─────────────────────────────────────────────────────────┘

逐项解释(对应上面的4个推荐勾选项):

选项 作用 为什么推荐
Install for all users 为计算机所有用户安装Python 避免其他用户使用时权限不足,也方便后续Windows服务以系统账户运行Python脚本
Associate files with Python 将.py文件关联到Python解释器 勾选后双击.py文件会直接用Python运行,而不是用记事本打开,调试脚本更方便
Create shortcuts for installed applications 在开始菜单创建快捷方式 方便快速打开Python自带工具(如IDLE、Python手册),对新手友好
Add Python to environment variables 将Python加入环境变量 与主界面的「Add Python to PATH」作用相同。如果主界面已勾选,这里会默认勾上,保持一致即可。它的本质是修改系统PATH,让命令行能识别python和pip

以下3项一般不勾:

选项 为什么不勾
Precompile standard library 预编译标准库会显著增加安装时间(几分钟),但对日常使用几乎没有性能提升。第一次导入模块时Python本来就会自动编译
Download debugging symbols 调试符号文件(约100MB+),只有当你需要自己调试Python解释器底层C代码时才用,99.9%的开发者用不到
Download debug binaries 调试版二进制文件(约200MB+),同上,普通开发完全不需要,只会白白占用硬盘空间

安装路径建议改为 D:\Python38(非C盘便于维护且不占用系统盘空间)。

2.3 验证安装

打开命令提示符(Win+R → cmd),输入:

python --version

应显示 Python 3.8.10。如果提示找不到命令,说明PATH未生效,请重新安装并勾选Add to PATH。

2.4 检查并升级pip

pip --version

如果显示旧版本(例如 pip 20.x),强烈建议升级到最新版:

python -m pip install --upgrade pip

为什么要升级pip?

· pip是Python的包管理工具,负责安装、卸载第三方库。
· 旧版本可能存在依赖解析错误、下载速度慢、无法识别新版包格式(如wheel)等问题。
· 升级可以避免后续安装Django、Waitress时出现莫名其妙的报错。

内网环境需要配置代理(内网需要代理上公网的情况):

pip install django==3.2 --proxy="http://proxy.example:8080" **(代理服务的名称和端口)**。

🔔 提示:如果你的电脑在内网,没有公网权限时,需要网络管理员给予配置正确的代理。没有公网权限时,pip install 安装各种包时会报错 SSL: CERTIFICATE_VERIFY_FAILED,此时需要网络管理员正确配置网络访问权限。

03 创建虚拟环境(隔离项目依赖)

关键理解:虚拟环境可以理解为5星酒店里的各个独立房间,房间A的配置不会影响房间B配置。创建虚拟环境的目的是安装在各个房间内的Djanog配置不因版本冲突、不因内容不一互相干扰。例如一个项目用Django 2.2,安装在房间A;另一个用3.2,安装在房间B,项目运行互不干扰。如果不使用虚拟环境,所有项目共用一套全局包,版本冲突会让程序无法正常运行。

cd D:\
mkdir JingFuWang
cd JingFuWang
python -m venv venv

命令解释:python -m venv 调用venv模块,最后一个venv是虚拟环境目录名(可自定义,但习惯用venv)。

3.1 激活虚拟环境

venv\Scripts\activate

激活后,命令行前面会出现 (venv) 标志。

Microsoft Windows [版本 6.1.7]
版权所有(c) 2009 Microsoft Corporatio。保留所有权利。

D:\>cd JingFuWang/venv/scripts回车			注释:进入scripts目录
D:\JingFuWang\venv\scripts>activate回车	注释:输入activate命令,启动虚拟环境
(venv) D:\JingFuWang\venv\scripts>			注释:虚拟环境已启动成功

⚠️ 黄金法则:激活虚拟环境后,应立即切换回项目根目录(即 D:\JingFuWang),因为 manage.py 在项目的根目录里。我们后续所有 pip install、python manage.py 都要在这个根目录执行。

cd D:\JingFuWang

3.2 退出虚拟环境

deactivate

04 安装Django和Waitress

确保虚拟环境已激活,命令行前有 (venv)。

pip install django==3.2
pip install waitress

为什么选择Django 3.2 LTS?
LTS(长期支持)版本会持续提供安全补丁,适合生产环境,且与本项目需要使用的第三方库兼容性好。

验证安装:

方法1:直接看版本(推荐)

django-admin --version

方法2:通过Python查看(更详细,可验证导入路径)
python -c “import django; print(django.get_version())”
输出应为 3.2。

05 创建Django项目(注意末尾的点)

命令末尾的“.”(点)不能省略,它表示在当前目录创建项目,而不是再套一层同名文件夹。

【情况一:不带点】
执行:

django-admin startproject GGGjypyg

生成的结构:

D:\JingFuWang\
└── JingFuWang\                 ← 多了一层外层目录
    ├── manage.py
    └── JingFuWang\             ← 项目配置目录
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py

问题:manage.py 在 GGGjypyg\ 下面,不是直接在 JingFuWang\ 根目录。
每次运行 python manage.py xxx 都要先 cd JingFuWang,麻烦。

【情况二:带点】(推荐)
执行:

django-admin startproject GGGjypyg .

生成的结构:

D:\JingFuWang\                ← 当前目录就是项目根目录
├── manage.py                 ← 直接在根目录,方便!
└── JingFuWang\                 ← 项目配置目录
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

好处:manage.py 就在 D:\JingFuWang\ 下面,想运行什么命令直接敲,不用切目录。

一句话:带点,manage.py 就在根目录;不带点,就给你多套一层JingFuWang/JingFuWang/,导致运行时路径混乱,python manage.py runserver 会找不到配置文件。

06 配置settings.py(生产环境必改项)

用编辑器(Notepad++或其它用的顺手的编辑器)打开 JingFuWang/settings.py,修改以下配置。

6.1 关闭调试模式

DEBUG = False

⚠️ 生产环境必须设为False。DEBUG=True时,出错会显示完整的堆栈信息、项目路径、SQL语句等,这是致命的敏感信息泄露。注意:永远不要在生产环境设置DEBUG=True。

6.2 配置允许访问的主机

ALLOWED_HOSTS = ['127.0.0.1', 'localhost', '19.74.8.18']

Django会根据请求的Host头进行校验,不在列表中的返回400。这是防止“主机头攻击”的安全措施。

6.3 设置时区和中文界面

TIME_ZONE = 'Asia/Shanghai'
LANGUAGE_CODE = 'zh-hans'

6.4 配置静态文件和媒体文件(文件末尾添加)

import os

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

· STATIC_ROOT:执行collectstatic后,所有静态文件会拷贝到此目录,由Nginx托管。
· MEDIA_ROOT:用户上传的文件存放位置。

6.5 (可选但推荐)安全增强配置

SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

这些配置要求Cookie只在HTTPS下传输,并信任Nginx转发的HTTPS协议,后续配置Nginx时会用到。

07 初始化数据库并创建超级用户

python manage.py migrate

migrate会根据Django内置模型(auth、admin、sessions等)创建数据库表,输出OK表示成功。

python manage.py createsuperuser

按提示输入用户名、邮箱、密码,用于登录Admin后台。

08 安装配置Nginx(反向代理+静态文件)

8.1 下载Nginx

访问 nginx.org/en/download.html,下载Windows稳定版(如 nginx-1.28.0.zip)。

解压到 D:\nginx,目录结构如下:

D:\nginx\
│
├── conf\                 	# 配置文件目录
│   └── nginx.conf        	# 主配置文件(核心。)
│
├── contrib\              	# 辅助工具
├── docs\                 	# 文档
├── html\                 	# 默认网站根目录
│   ├── index.html        	# 默认首页
│   └── 50x.html          	# 错误页面
├── logs\                 	# 日志目录(启动后自动生成)
│   ├── access.log        	# 访问日志
│   └── error.log        	 # 错误日志
├── temp\                 	# 临时文件
└── nginx.exe             	# 主程序

8.2 测试Nginx

D:
cd D:\nginx
start nginx

浏览器访问 http://127.0.0.1,看到“Welcome to nginx!”即成功。

常用命令:

· nginx -s stop – 快速停止
· nginx -s quit – 优雅停止
· nginx -s reload – 重载配置(修改配置后使用)

09 生成SSL自签名证书(内网HTTPS必备)

内网环境可以使用自签名证书,成本低、部署快。证书的CN必须与用户访问的IP/域名完全一致,否则浏览器会报安全错误。

9.1 安装pyOpenSSL

pip install pyOpenSSL

9.2 创建证书生成脚本 gen_ssl.py

在项目根目录 D:\JingFuWang 下创建文件 gen_ssl.py,内容如下:

from OpenSSL import crypto
import os

ssl_dir = r"D:\JingFuWang\ssl"
if not os.path.exists(ssl_dir):
    os.makedirs(ssl_dir)

# 生成私钥
key = crypto.PKey()
key.generate_key(crypto.TYPE_RSA, 2048)

# 生成证书
cert = crypto.X509()
cert.get_subject().C = "CN"
cert.get_subject().ST = "Heilongjiang"
cert.get_subject().L = "Daqing"
cert.get_subject().O = "Security Dept"
cert.get_subject().CN = "19.74.8.18"   # 改为你的服务器IP或域名

cert.set_serial_number(1000)
cert.gmtime_adj_notBefore(0)                 # 现在生效
cert.gmtime_adj_notAfter(3650*24*60*60)      # 10年有效期
cert.set_issuer(cert.get_subject())
cert.set_pubkey(key)
cert.sign(key, 'sha256')

# 保存
with open(os.path.join(ssl_dir, "server.key"), "wb") as f:
    f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key))
with open(os.path.join(ssl_dir, "server.crt"), "wb") as f:
    f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))

print("SSL证书生成完成!")
print(f"证书:{ssl_dir}\\server.crt")
print(f"私钥:{ssl_dir}\\server.key")

9.3 执行生成

python gen_ssl.py

成功后 D:\JingFuWang\ssl 目录下会出现 server.crt 和 server.key。

🔔 最容易踩的坑:证书的CN必须与用户浏览器访问的IP完全一致。如果你用 https://192.168.1.100 访问,但证书CN写的是 19.74.8.18,浏览器会报 NET::ERR_CERT_COMMON_NAME_INVALID。

10 配置Nginx反向代理(核心,最容易出错的地方)

用编辑器打开 D:\nginx\conf\nginx.conf,建议先备份。将内容替换为以下配置(根据实际IP和路径修改):

worker_processes 1;
error_log D:/nginx/logs/error.log warn;
pid D:/nginx/logs/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;
    server_tokens off;        # 隐藏Nginx版本号
    client_max_body_size 20M;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log D:/nginx/logs/access.log main;

    # HTTP服务:80端口强制跳转HTTPS
    server {
        listen 80;
        server_name 19.74.8.18;
        return 301 https://$host$request_uri;
    }

    # HTTPS主服务
    server {
        listen 443 ssl;
        http2 on;
        server_name 19.74.8.18;

        ssl_certificate D:/JingFuWang/ssl/server.crt;
        ssl_certificate_key D:/JingFuWang/ssl/server.key;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;

        # 安全响应头
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-XSS-Protection "1; mode=block" always;

        # 静态文件直接由Nginx处理
        location /static/ {
            alias D:/JingFuWang/static/;
            expires 30d;
            access_log off;
        }
        location /media/ {
            alias D:/JingFuWang/media/;
            access_log off;
        }

        # 动态请求反向代理到Waitress
        location / {
            proxy_pass http://127.0.0.1:8000;
            # 必须转发的请求头(尤其Cookie!)
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Cookie $http_cookie;   # 最容易遗忘!
            proxy_set_header Referer $http_referer;

            proxy_connect_timeout 60s;
            proxy_read_timeout 60s;
            proxy_send_timeout 60s;
        }

        # 禁止访问隐藏文件和敏感文件
        location ~ /\. {
            deny all;
        }
        location ~* \.(py|pyc|sqlite|db|env|ini|log|sh|bak)$ {
            deny all;
        }
    }
}

🔥 最容易踩的坑: proxy_set_header Cookie $http_cookie;
如果不转发Cookie,Django接收不到sessionid和csrftoken,会导致登录后点击任何链接又跳回登录页,或者POST请求返回403。这是被问到最多的问题,没有之一!

测试配置文件

nginx -t

输出 test is successful 后,重载Nginx:

nginx -s reload

11 收集静态文件并手动启动测试

11.1 收集静态文件

cd D:\JingFuWang
venv\Scripts\activate
python manage.py collectstatic

输入 yes,所有静态文件会被复制到 D:\JingFuWang\static。

11.2 创建媒体目录(可选)

mkdir D:\JingFuWang\media

11.3 手动启动Waitress(先不配置开机自启)

waitress-serve --listen=127.0.0.1:8000 JingFuWang.wsgi:application

看到 INFO:waitress:Serving on http://127.0.0.1:8000 表示启动成功。

此时Nginx应该已经是运行状态(上一步已启动或重载)。如果之前停止了,执行 start nginx 重新启动。

11.4 浏览器访问

打开浏览器,访问 https://19.74.8.18/admin/。因为使用自签名证书,会提示“不安全”,点击“高级”→“继续访问”。
使用之前创建的超级用户登录,如果能正常进入Django Admin后台,说明部署成功!

12 常见问题排查(最容易踩的坑汇总)

现象 可能原因 解决方法
浏览器显示502 Bad Gateway Waitress未启动或端口不一致 检查 netstat -an | findstr “8000”,确保127.0.0.1:8000在监听;双击启动脚本
访问网站显示403 Forbidden Nginx恶意请求拦截 (URL含敏感词)或IP不在白名单 检查URL参数;若正常请求被误拦,可临时调整 map $bad_request 规则
登录后点击任何链接又跳回登录页 Nginx未转发Cookie 确认nginx.conf中有 proxy_set_header Cookie $http_cookie;
静态文件404(页面无样式) 未执行collectstatic或alias路径错误 执行 python manage.py collectstatic,检查static目录是否存在,alias路径末尾加/
HTTPS访问时Django生成http://链接 未配置X-Forwarded-Proto和SECURE_PROXY_SSL_HEADER 确认nginx.conf中有 proxy_set_header X-Forwarded-Proto $scheme;,且在settings.py中设置了 SECURE_PROXY_SSL_HEADER = (‘HTTP_X_FORWARDED_PROTO’, ‘https’)
python 不是内部或外部命令 安装Python时未勾选Add to PATH 重新安装并勾选,或手动将Python路径加入系统PATH
pip安装包时报错“SSL: CERTIFICATE_VERIFY_FAILED” 内网代理或证书问题 使用 pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org 或配置代理
浏览器报 NET::ERR_CERT_COMMON_NAME_INVALID 证书CN与访问IP不一致 重新生成证书,将CN改为实际访问的IP或域名

13 小结

恭喜!你已完成Windows下Django生产环境的完整部署:

步骤 核心操作 关键理解
安装Python 勾选Add to PATH PATH 决定命令行能否找到python
升级pip python -m pip install --upgrade pip 避免旧版本依赖解析错误
虚拟环境 python -m venv venv 隔离项目依赖
配置settings DEBUG=False, ALLOWED_HOSTS 生产安全基线
Nginx配置 proxy_set_header Cookie 保证登录状态
SSL证书 自签名脚本 CN必须与访问IP一致
收集静态文件 collectstatic 集中管理静态资源

目前服务还是手动启动的,服务器重启后需要再次手动操作。

📌下期预告:下一章(第三篇)《永不消逝的电波——开机自启脚本+Windows任务计划,让服务24小时在线》。敬请关注,连载中。

📌 欢迎关注,你在部署时遇到过什么奇葩报错?评论区聊聊

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐