Django 生产环境如何部署静态文件:collectstatic、STATIC_ROOT 与分发
【免费下载链接】djangoThe Web framework for perfectionists with deadlines.项目地址: https://gitcode.com/GitHub_Trending/dj/django
把 Django 项目投入生产后,图片、JavaScript、CSS 这类静态文件不能继续依赖开发服务器。Django 提供的标准做法是两步:在静态文件发生变化时运行collectstatic命令把所有静态文件收集到STATIC_ROOT目录,再把收集好的目录交给 Web 服务器(或存储后端)对外分发。本文基于 Django 官方文档 静态文件部署指南 与 staticfiles 参考,梳理一条从配置到验证的完整路径。
适用前提:项目使用django.contrib.staticfiles(默认项目模板已包含),并且你能够修改settings.py以及在部署目标上执行管理命令。
配置 settings:STATIC_URL、STATIC_ROOT 与 STATICFILES_DIRS
在 settings 文件中完成三件事:
确认
INSTALLED_APPS包含django.contrib.staticfiles。定义
STATIC_URL,它是指向静态文件时使用的 URL 前缀,非空值必须以斜杠结尾。文档给出的示例值:"static/"或"https://static.example.com/"。STATIC_URL = "static/"如果
STATIC_URL是相对路径,它会被服务器提供的SCRIPT_NAME值(未设置时为/)作为前缀,这让 Django 应用部署在子路径下时不必额外配置。设置
STATIC_ROOT为collectstatic收集文件的绝对路径,例如:STATIC_ROOT = "/var/www/example.com/static/"注意文档中的警告:
STATIC_ROOT应是一个初始为空的目标目录,只用于把静态文件从永久存放位置集中起来以便部署,不是静态文件的永久存放处。文件的永久位置应放在 staticfiles 的 finders 能找到的地方——默认即各应用的static/子目录,以及STATICFILES_DIRS中列出的目录。
静态文件本身的存放约定:
应用内的文件放在该应用的
static目录下,例如my_app/static/my_app/example.jpg。文档特别提醒不要直接把文件放在my_app/static/下再省掉一层应用名目录:Django 使用按名称匹配找到的第一个文件,不同应用中同名文件无法区分,用应用名做命名空间才能避免歧义。不属于任何应用的公共静态资源,通过
STATICFILES_DIRS指定额外目录,路径用 Unix 风格正斜杠(Windows 上也是):STATICFILES_DIRS = [ BASE_DIR / "static", "/var/www/static/", ]STATICFILES_DIRS还支持可选的(prefix, path)元组形式,给某个目录加命名空间。例如("downloads", "/opt/webfiles/stats")且STATIC_URL为"static/"时,collectstatic会把这些文件收集到STATIC_ROOT下的downloads/子目录。
模板中用{% static %}标签生成 URL,它按配置的staticfilesstorage 前缀拼接路径:
{% load static %} <img src="{% static 'my_app/example.jpg' %}" alt="My image">运行 collectstatic 收集文件
配置完成后执行:
$ python manage.py collectstatic该命令会用STATICFILES_FINDERS中启用的 finders 搜索文件(默认在STATICFILES_DIRS和各应用的static/目录中查找),并把结果复制进STATIC_ROOT。
两个影响重复执行的行为需要知道:
- 同名文件按类似模板解析的规则解决:在指定位置中首先找到的文件胜出。拿不准时可用
findstatic命令查看某个相对路径会命中哪些文件。 - 再次运行时(
STATIC_ROOT非空),只有当源文件修改时间戳大于STATIC_ROOT中已有文件时才会复制。因此如果你从INSTALLED_APPS中移除了某个应用,建议用--clear选项先清掉过期的静态文件。
常用选项(来自 staticfiles 参考):
| 选项 | 用途 |
|---|---|
--dry-run/-n | 除不修改文件系统外,执行所有步骤;用于先预览影响 |
--clear/-c | 复制前清空现有文件 |
--ignore PATTERN/-i | 忽略匹配 glob 模式的文件、目录或路径,可多次使用;路径一律用正斜杠 |
--link/-l | 创建符号链接而不是复制文件 |
--noinput/--no-input | 不以任何形式向用户请求输入 |
--no-post-process | 不调用staticfilesstorage 后端的post_process方法 |
完整选项列表可用python manage.py collectstatic --help查看。
findstatic是定位“到底会收集到哪个文件”的调试工具:
$ python manage.py findstatic css/base.css admin/js/core.js文档示例输出(示意命中结果,非固定预期):
Found 'css/base.css' here: /home/special.polls.com/core/static/css/base.css /home/polls.com/core/static/css/base.css Found 'admin/js/core.js' here: /home/polls.com/src/django/contrib/admin/media/js/core.js加--first只返回每个路径的第一个匹配,加--verbosity 0只输出路径名,加--verbosity 2还会列出所有被搜索的目录。
把 STATIC_ROOT 交给 Web 服务器分发
收集完成后,让 Web 服务器在STATIC_URL下提供STATIC_ROOT中的文件。文档给出几种常见模式,按目标拓扑选择其一即可。
模式一:与站点同一台服务器(Apache + mod_wsgi 示例)
流程:把代码推到部署服务器 → 在服务器上运行collectstatic→ 配置 Web 服务器在STATIC_URL下提供STATIC_ROOT中的文件。文档指出如果有多个 Web 服务器,这个过程最好自动化。
如果只能用运行 Django 的同一个 ApacheVirtualHost分发静态文件,可以按 Apache 与 mod_wsgi 指南 中的“Serving files”一节做Alias配置。下面这份配置中的/path/to/mysite.com是文档中的占位路径,需要替换为你的项目实际路径,其中/static/指向的内容应替换为你的STATIC_ROOT实际位置:
Alias /robots.txt /path/to/mysite.com/static/robots.txt Alias /favicon.ico /path/to/mysite.com/static/favicon.ico Alias /media/ /path/to/mysite.com/media/ Alias /static/ /path/to/mysite.com/static/ <Directory /path/to/mysite.com/static> Require all granted </Directory> <Directory /path/to/mysite.com/media> Require all granted </Directory> WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py <Directory /path/to/mysite.com/mysite> <Files wsgi.py> Require all granted </Files> </Directory>文档同时强调:即使使用其他服务器方案,只要没有专门的静态服务器,也要自己负责配置服务器来提供 admin 静态文件(它们位于 Django 发行版的django/contrib/admin/static/admin)。文档强烈建议用staticfiles处理 admin 文件,即运行collectstatic收集到STATIC_ROOT,再让 Web 服务器在STATIC_URL下提供STATIC_ROOT。
模式二:独立静态服务器(可选分支)
较大的站点通常使用一台不运行 Django 的独立 Web 服务器分发静态文件,常见选择是 Nginx 或精简配置的 Apache。这类服务器的具体配置在 Django 文档范围之外,需查阅各自文档。部署策略变为:
- 静态文件变化时,在本地运行
collectstatic; - 把本地
STATIC_ROOT推送到静态服务器被提供的目录,文档推荐rsync,因为它只传输有变化的部分。
模式三:云存储 / CDN(可选分支)
静态文件也可以放到 S3 这类云存储和 CDN 上。做法与前面相同,只是把文件传输目标换成存储提供商。如果提供商有 API,可以编写自定义文件存储后端,并把STORAGES中staticfiles别名指向它:
STORAGES = { # ... "staticfiles": {"BACKEND": "myproject.storage.S3Storage"} }配置完成后只需运行collectstatic,文件就会经该存储后端推送到 S3。之后切换存储提供商时,可能只需修改STORAGES中的staticfiles项。编写自定义后端的细节见 自定义文件存储。
可选:用 ManifestStaticFilesStorage 支持长缓存
如果希望给部署的文件使用很长的 Expires 头、并在缓存的页面仍引用旧文件时继续可用,可以把STORAGES的staticfiles后端设为django.contrib.staticfiles.storage.ManifestStaticFilesStorage。它在保存文件名时追加内容 MD5 哈希,例如css/styles.css会同时存为css/styles.55e7cbb9ba48.css,并在post_process阶段自动把保存文件中引用的其他静态文件路径替换为带哈希的版本(覆盖 CSS 的@import/url()以及 CSS、JavaScript 中的 source map 注释)。
启用条件,三条缺一不可(来自 staticfiles 参考):
STORAGES中staticfiles后端设为'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'DEBUG为False- 已用
collectstatic收集了全部静态文件
哈希映射只计算一次并保存在STATIC_ROOT下的staticfiles.json中。运行时若某文件不在 manifest 里,默认抛出ValueError;子类化并把manifest_strict设为False可让缺失路径原样保留。文档还明确:由于依赖collectstatic,测试时不要使用此 storage,应换回默认的StaticFilesStorage(测试中collectstatic不在常规测试流程内)。
验证与边界
- 验证收集结果:
collectstatic之后检查STATIC_ROOT中是否出现各应用的静态子目录和公共目录内容;文件命中不明时用findstatic <相对路径>复核。 - 不要在生产用 Django 开发服务器分发静态文件:
runserver在DEBUG = True时自动提供的静态服务,文档明确评价为“极其低效且可能不安全,不适合生产”;runserver --insecure(即使DEBUG为False也强制服务)只用于本地开发,不应在生产使用。 - 权限:默认收集的文件权限来自
FILE_UPLOAD_PERMISSIONS、目录权限来自FILE_UPLOAD_DIRECTORY_PERMISSIONS。如需不同值,可子类化 storage 并传入file_permissions_mode/directory_permissions_mode参数,再把STORAGES的staticfiles后端指向该子类。 MEDIA_ROOT与STATIC_ROOT必须不同:MEDIA_ROOT是用户上传文件的存放目录,不属于本文的静态文件收集范围,不要把两者指向同一目录。
更多细节(static标签行为、StaticLiveServerTestCase测试支持等)可继续参考 管理静态文件指南 和 staticfiles 参考。
【免费下载链接】djangoThe Web framework for perfectionists with deadlines.项目地址: https://gitcode.com/GitHub_Trending/dj/django
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考