Django 在 DEBUG=False 时不再自动提供静态文件,必须通过 Nginx 等 Web 服务器直接映射 STATIC_ROOT 目录,且需确保 collectstatic 在部署机运行、STATIC_ROOT 与 Nginx alias 路径一致、INSTALLED_APPS 包含 'django.contrib.staticfiles'。

DEBUG=False 时 Django 不再自动提供静态文件
这是最常被忽略的前提:Django 只在 DEBUG=True 时,才通过 django.contrib.staticfiles 自动响应 /static/ 请求;一旦设为 False(生产环境必须),这个能力就完全关闭——它不会报错,但所有 GET /static/xxx.js 请求都会直接 404。
这不是配置错了,而是机制切换了。你必须明确告诉 Web 服务器(如 Nginx)或 Django 自身“去哪找这些文件”。
STATIC_ROOT 必须指向 collectstatic 输出目录,且不能和 STATICFILES_DIRS 重叠
STATIC_ROOT 是一个**只写、只用于部署**的路径,比如 BASE_DIR / "staticfiles"。它和开发时放源文件的 static/ 目录必须物理隔离。
-
STATICFILES_DIRS指向你手写的源文件位置(如BASE_DIR / "static"),仅用于开发和collectstatic扫描 -
STATIC_ROOT是空目录,python manage.py collectstatic会把所有静态文件(app 内 +STATICFILES_DIRS)一股脑复制进去 - 如果误把
STATIC_ROOT设成BASE_DIR / "static",collectstatic会清空你的源码目录,导致二次部署失败
生产环境不靠 Django serve,要靠 Nginx 或 Apache 直接映射
在 DEBUG=False 下,硬要在 urls.py 里加 static(...) 路由是危险且低效的——Django 进程会变成静态文件瓶颈,还可能暴露敏感路径。
立即学习“Python免费学习笔记(深入)”;
正确做法是在 Nginx 配置中直接 alias:
location /static/ {
alias /path/to/your/project/staticfiles/;
}
注意两点:
-
location末尾的/和alias末尾的/必须匹配,否则路径拼接错误(例如请求/static/js/app.js会去找/path/.../staticfiles/js/app.js,而非/path/.../staticfiles/js/app.js) -
alias后面是**绝对路径**,不是相对路径;Nginx 进程必须有该目录的读取权限
collectstatic 必须在部署目标机器上运行,且路径要一致
很多人在本地跑 collectstatic,然后把 staticfiles/ 文件夹整个上传——这容易因路径差异失效。更稳妥的做法是:
- 在部署机上执行
python manage.py collectstatic --noinput - 确保部署机上的
settings.py中STATIC_ROOT路径与 Nginx 的alias完全一致 - 确认
INSTALLED_APPS包含'django.contrib.staticfiles',否则collectstatic不会扫描 app 内的static/目录
最后检查点:浏览器开发者工具 Network 标签页里,点击 404 的 JS/CSS 请求,看完整 URL 是什么——它决定了你要配 Nginx 的 location 前缀,而不是反过来猜。


















