正确做法是在视图中拼好完整路径(如context['css_url'] = f'css/{theme}.css'),模板中用{% static css_url %};django模板不支持{% static 'css/{{ theme }}.css' %}这类变量嵌套,否则将导致404。

直接用 {% static %} 标签拼路径会出错
很多人写成 {% static 'css/{{ theme }}.css' %},这根本不会解析变量,Django 模板引擎不支持在 {% static %} 内部嵌套变量。浏览器最终请求的是字面量路径 /static/css/{{ theme }}.css,404 是必然结果。
正确做法是先拼好完整路径字符串,再交给 {% static %} 处理。但注意:Django 2.0+ 的 {% static %} 不接受变量参数,必须用 static 模板过滤器。
- 确保已加载
{% load static %} - 用
{{ theme|add:'css/'|add:'.css'|static }}这类链式过滤器拼接(add过滤器只能拼字符串,不能加斜杠以外的字符) - 更稳妥的方式是在视图里拼好完整路径,比如
context['css_url'] = f'css/{theme}.css',模板中直接写{% static css_url %}
用 django-compressor 或 django-webpack-loader 时别绕过构建流程
如果你项目启用了前端资源打包工具(比如 Webpack),直接按变量名引入 CSS 文件会导致缓存失效或资源未构建。例如 {% static 'css/dark.css' %} 可能对应实际文件 css/dark.abc123.css,而变量值没经过哈希处理,就找不到带 hash 的版本。
- 不要在模板里动态拼接原始文件名,改用后端传入的已解析路径(如
context['theme_css'] = webpack_static('css/dark.css')) - 若用
django-compressor,它不支持运行时选择 CSS 文件;主题切换必须靠独立的{% compress %}块 + 视图控制是否渲染某一块 - 静态文件 URL 必须和实际构建输出一致,否则 CDN 缓存、浏览器缓存都会出问题
避免在模板里做逻辑判断引入不同 CSS
有人写 {% if theme == 'dark' %}<link href="%7B%%20static%20'css/dark.css'%20%%7D" rel="stylesheet">{% else %}<link href="%7B%%20static%20'css/light.css'%20%%7D" rel="stylesheet">{% endif %},看似可行,但维护成本高、易漏写、难复用。
- 把这类判断提到视图层,统一生成
css_url,模板只负责渲染一个<link> - 如果主题来自用户配置(如数据库字段),记得在视图里校验
theme是否在白名单中(['light', 'dark', 'blue']),防止路径遍历或 XSS(比如theme=../../etc/passwd) - 前端 JS 切换主题时,后端仍需同步更新 session 或 profile,否则刷新后样式丢失
开发环境与生产环境路径差异导致本地正常线上 404
本地用 runserver 时 {% static %} 直接映射到 STATICFILES_DIRS,但生产环境依赖 collectstatic 后的 STATIC_ROOT。如果变量拼出的路径不在收集范围内(比如 css/custom-{{ user.id }}.css),线上肯定 404。
- 所有可能被变量引用的 CSS 文件,必须提前放在
static/css/下并纳入版本管理,不能靠运行时生成 - 检查
python manage.py collectstatic --dry-run输出,确认目标文件被列出 - 若真需要动态生成 CSS(如配色方案导出),应走视图返回
Content-Type: text/css,而不是塞进 static 目录
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











