STATICFILES_STORAGE必须替换为支持CDN的存储类,如自定义CDNStaticStorage或django-storages后端;否则collectstatic仍写本地,导致CDN路径文件缺失。

STATICFILES_STORAGE 配置必须用自定义类
Django 默认的 StaticFilesStorage 会把静态文件写入本地 STATIC_ROOT,无法直接推送到 CDN。要走 CDN,必须替换为支持远程上传的存储后端——比如 django-storages 提供的 S3Boto3Storage(适配 AWS S3 / 兼容 S3 的 CDN),或自己写一个轻量级类来拼接 CDN 域名前缀。
常见错误是只改了 STATIC_URL 却没动 STATICFILES_STORAGE,结果 collectstatic 还是往本地写,页面里生成的 URL 虽然带 CDN 域名,但文件根本不存在。
- 若用对象存储型 CDN(如 Cloudflare R2、腾讯云 COS、又拍云),装
django-storages并配置对应 backend - 若用纯回源型 CDN(如阿里云 CDN、Cloudflare CDN),只需自定义一个只改 URL 前缀、不上传文件的 storage 类
- 无论如何,
DEBUG = False时必须运行python manage.py collectstatic,否则模板中{% static %}不会生效
自定义 CDN StaticStorage 类最简单可靠
很多团队不需要 Django 管理上传,只要 HTML 中引用的 /static/js/app.js 自动变成 https://cdn.example.com/static/js/app.js——这时写一个继承 StaticFilesStorage 的类就够了:
from django.contrib.staticfiles.storage import StaticFilesStorage
class CDNStaticStorage(StaticFilesStorage):
def __init__(self, *args, **kwargs):
self.cdn_host = kwargs.pop('cdn_host', '')
super().__init__(*args, **kwargs)
def url(self, name, **kwargs):
url = super().url(name, **kwargs)
if self.cdn_host and url.startswith('/'):
url = self.cdn_host + url
return url
然后在 settings.py 里启用:
STATICFILES_STORAGE = 'myproject.storage.CDNStaticStorage'
STATICFILES_STORAGE_KWARGS = {'cdn_host': 'https://cdn.example.com'}
注意:STATICFILES_STORAGE_KWARGS 是 Django 4.2+ 才支持的传参方式;旧版本需在类里硬编码或从环境变量读取。
collectstatic 不上传但必须运行
用纯 CDN 回源模式时,collectstatic 的作用不是“发文件”,而是“生成带哈希的文件名”和“更新 staticfiles.json”。如果跳过这步,{% static 'app.js' %} 就不会自动加版本号(如 app.a1b2c3.js),缓存就无法安全更新。
- CDN 回源路径必须指向你部署的
STATIC_ROOT目录(例如 Nginx 的alias /var/www/myproject/static/;) - 确保
STATIC_ROOT已被collectstatic填满,且 Web 服务器能读取该目录 - 不要在
DEBUG=True下依赖whitenoise或开发服务器提供静态文件——它不触发url()方法,CDN 前缀不会生效
模板里 {% static %} 和硬编码 URL 的区别
写死 <script src="https://cdn.example.com/static/app.js"></script> 看似省事,但会绕过 Django 的静态文件管理机制:无法自动加哈希、不能用 ManifestStaticFilesStorage 做完整性校验、也不受 WHITENOISE_MANIFEST_STRICT 等控制。
真正需要 CDN 加速的,往往是已上线项目,这时候缓存一致性比少敲几个字符重要得多。
所以坚持用 {% load static %} + {% static 'app.js' %},哪怕多写两行,也比后期排查 “为什么改了 JS 用户还是看到旧逻辑” 强。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











