根本原因是模板渲染在服务端完成,js执行在浏览器端,{{ var }}语法仅在django模板引擎中有效;json_script标签将python对象安全序列化为json并嵌入type="application/json"脚本标签,实现数据与逻辑分离、自动转义防xss、类型兼容性强。

Django 模板变量在 JS 中直接写 {{ var }} 会出错,根本原因是:模板渲染和 JS 执行发生在完全不同的阶段、不同的环境里。
模板渲染发生在服务端,JS 解析发生在浏览器端
Django 模板引擎在服务器上运行,把 {{ some_dict }}、{{ user.id }} 这类语法替换成实际值(比如 {"name": "Alice"} 或 123),生成纯 HTML 字符串后发给浏览器。而 JS 脚本是在浏览器里解析执行的,它根本“看不到”也没法处理 {{ }} 这种 Django 专属语法 —— 它连 Django 都不认识。
常见错误现象包括:
- 浏览器控制台报
Uncaught SyntaxError: Unexpected token '{'(因为没转义的字典被原样塞进 JS) - 字符串中出现换行或双引号导致 JS 语法中断
- 用户输入内容未过滤,直接拼进 JS 引发 XSS(例如
{{ user_comment }}是"'; alert(1); //)
json_script 是最安全、最推荐的传递方式
Django 2.1+ 内置的 json_script 标签,专为解决这个问题设计:它把 Python 对象序列化成合法 JSON,并包裹在 <script type="application/json"></script> 标签里,既不执行、也不污染 JS 作用域。
用法很简单:
- 模板中:
{% json_script data "my-data" %}(data是视图传来的上下文变量,"my-data"是 script 标签的id) - 外部 JS 中:
const data = JSON.parse(document.getElementById('my-data').textContent);
优势在于:
- 自动处理嵌套结构、日期、Decimal 等类型(靠
DjangoJSONEncoder) - 所有字符都经过双重转义(HTML + JSON),杜绝 XSS
- 数据与逻辑彻底分离,外部 JS 文件可复用、可缓存、可压缩
为什么不用 <script>var myData = {{ data|json_script }}</script>?
这种写法看似简洁,但存在几个硬伤:
-
|json_script不是过滤器,是模板标签,不能这么用 —— 会直接报Invalid block tag - 即使改用
|safe+|escapejs组合,也难以覆盖所有边界情况(比如None→null、datetime序列化格式) - 手动拼接容易漏掉引号闭合或换行转义,调试时 JS 报错位置和模板位置对不上
- 无法利用
json_script自带的 DOM ID 查找机制,后续维护成本高
复杂对象或需要前端动态更新时要注意什么
json_script 只负责“一次性”注入初始数据。如果你的数据后续会变(比如用户操作触发 API 请求拿到新列表),就不能依赖它实时更新 —— 它只在页面加载时生效一次。
这时候要明确分工:
- 静态配置、初始化参数(如图表默认选项、权限标识)→ 用
json_script - 动态业务数据(如搜索结果、表单校验反馈)→ 走独立 API 接口,用
fetch或axios获取
最容易被忽略的一点:别在 json_script 里塞大量冗余字段。比如只用到 user.name 和 user.avatar_url,就不要传整个 User 实例 —— 序列化开销、网络传输、内存占用都会增加,且暴露更多后端结构。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










