当前位置: 首页
前端开发
Django 中安全传递 JSON 数据到前端的正确方法

Django 中安全传递 JSON 数据到前端的正确方法

热心网友 时间:2026-04-29
转载

在 Django 中安全传递 JSON 数据到前端的正确方法

Django 中安全传递 JSON 数据到前端的正确方法

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

在 Django 项目里,一个常见的需求是把后端查询到的结构化数据——比如用户的体重记录——传递给前端 Ja vaScript,以便绘制图表或实现动态交互。然而,这里有个高频“踩坑点”:很多开发者会直接把 Python 的字面量(例如一个列表或字典)塞进 HTML 的 `data-*` 属性里。这种做法不仅无效,而且相当危险。你得到的其实是 Python 的 `repr()` 字符串表示,里面充斥着单引号,特殊字符也没有被转义,这根本不是符合 RFC 8259 规范的标准 JSON。结果就是,前端的 `JSON.parse()` 会毫不犹豫地抛出一个语法错误:`SyntaxError: expected property name or '}'`。

✅ 核心原则:务必使用 json.dumps() 生成合法 JSON

Django 本身并不会帮你自动完成 JSON 序列化,这一步必须由开发者显式调用 Python 标准库的 `json.dumps()` 来完成。这个函数确保了输出的字符串是“干净”的:

  • 键和字符串值由双引号包裹;
  • 换行符、引号、反斜杠等特殊字符会被自动转义;
  • 默认输出 UTF-8 编码的纯文本;
  • 还可以通过 `separators=(',', ':')` 参数来压缩不必要的空格,优化传输体积。

那么,如何修正视图代码呢?来看一个改造后的例子:

import json  # 推荐显式 import,更清晰
from django.core.paginator import Paginator
from django.shortcuts import render, redirect
from .models import WeightRecord, Profile
from .forms import WeightLogForm

def profile_page(request):
    if request.method == 'POST':
        form = WeightLogForm(request.POST)
        if form.is_valid():
            weight_log = form.sa ve(commit=False)
            weight_log.profile = Profile.objects.get(user=request.user)
            weight_log.sa ve()
            return redirect('profile')
    else:
        form = WeightLogForm()

    user_weight_log = WeightRecord.objects.filter(
        profile__user=request.user
    ).order_by('-entry_date')
    paginator = Paginator(user_weight_log, 10)
    page = request.GET.get('page')
    try:
        user_weight_log = paginator.page(page)
    except PageNotAnInteger:
        user_weight_log = paginator.page(1)
    except EmptyPage:
        user_weight_log = paginator.page(paginator.num_pages)

    # ✅ 关键修正:用 json.dumps() 生成标准 JSON 字符串
    serialized_data = json.dumps([
        {
            'weight': str(record.weight),
            'entry_date': record.entry_date.strftime('%Y-%m-%d')
        }
        for record in user_weight_log
    ])

    return render(request, 'profile.html', {
        'user_weight_log': user_weight_log,
        'form': form,
        'weight_data': serialized_data  # 此时已是合法 JSON 字符串
    })

在对应的模板中,由于 `json.dumps()` 输出的已经是安全的纯文本字符串(不包含 `<`、`>`、`&` 等 HTML 特殊字符),我们仍然需要使用 `|safe` 过滤器来告诉 Django 不要对它进行额外的 HTML 转义:

这样一来,前端 Ja vaScript 就能安全、顺畅地解析数据了:

const weightDataElement = document.getElementById('weight-data');
const weightDataJSON = weightDataElement.getAttribute('data-weight-data');
const weightData = JSON.parse(weightDataJSON); // ✅ 现在完全合法
console.log(weightData); // [{weight: "122.00", entry_date: "2023-09-28"}, ...]

⚠️ 几个必须留意的细节

  • 切忌手动拼接 JSON 字符串:比如用字符串加法拼凑出 `'{' + ... + '}'`,这极易引入难以调试的语法错误,是绝对的“反模式”。
  • 处理非 ASCII 字符:如果数据包含中文等字符,`json.dumps()` 默认会将其转义为 `\uXXXX` 形式。若希望在前端保持可读性,可以传入参数 `ensure_ascii=False`,但务必确保你的 HTTP 响应编码正确设置为 UTF-8。
  • 性能考量:对于数据量非常大的情况,不建议直接将海量 JSON 嵌入 HTML。更好的做法是创建专门的 API 端点,通过 `fetch` 或 `axios` 异步加载数据。
  • 更优的官方方案:Django 4.2 及以上版本提供了一个更优雅的解决方案——`|json_script` 模板过滤器。它尤其适合处理复杂或敏感数据。这个过滤器会将数据写入一个 `