如何在JavaScript中处理Django传递的字典数据?
解决Django模板向JS传递卡片数据的问题
核心问题分析
你当前的问题在于直接在模板中使用{{ cards }}输出Python列表,得到的是Python风格的字符串(比如[{'front': 'xxx', ...}]),这种格式不是标准JSON,JS无法直接解析成对象,所以会出现多余的{、[、'符号。
正确的传递方式
方法1:使用Django的json_script过滤器(推荐)
Django内置的json_script过滤器会把Python序列转成安全的JSON字符串,并包裹在<script>标签里,避免XSS风险且格式正确。
修改模板文件:
{% extends "srs/layout.html" %} {% load static %} {% block body %} <div class="body-container"> <p class="front"></p> <p class="back"></p> <button id="show-answer">Show Answer</button> <button id="next-card">Next</button> </div> <!-- 用json_script生成安全的JSON数据 --> {{ cards|json_script:"cards-data" }} <script src="{% static 'srs/learn.js' %}"></script> {% endblock %}
方法2:手动转JSON并转义(不推荐,不如方法1安全)
如果不想用json_script,可以在视图中用json.dumps把cards转成JSON字符串,然后在模板中输出:
修改视图函数:
import json from django.shortcuts import get_object_or_404 def learn(request, deck_id): deck = get_object_or_404(Deck, pk=deck_id) cards_queryset = deck.cards.all() cards = [{'front': card.front, 'back': card.back} for card in cards_queryset] # 转成JSON字符串 cards_json = json.dumps(cards) return render(request, 'srs/learn.html', { 'deck': deck, 'cards_json': cards_json, })
然后模板中这样写:
<div id="cards-var" data-cards="{{ cards_json|escapejs }}"></div>
在JS中访问数据
以方法1为例,在learn.js中解析并使用数据:
// 获取JSON数据并解析成JS数组 const cards = JSON.parse(document.getElementById('cards-data').textContent); // 初始化当前卡片索引 let currentCardIndex = 0; // 显示当前卡片的正面 function showCurrentCardFront() { const frontElement = document.querySelector('.front'); const backElement = document.querySelector('.back'); frontElement.textContent = cards[currentCardIndex].front; backElement.textContent = ''; // 隐藏背面 } // 显示当前卡片的背面 function showCurrentCardBack() { const backElement = document.querySelector('.back'); backElement.textContent = cards[currentCardIndex].back; } // 切换到下一张卡片 function nextCard() { currentCardIndex = (currentCardIndex + 1) % cards.length; showCurrentCardFront(); } // 绑定按钮事件 document.getElementById('show-answer').addEventListener('click', showCurrentCardBack); document.getElementById('next-card').addEventListener('click', nextCard); // 页面加载时显示第一张卡片 window.addEventListener('load', showCurrentCardFront);
关于拆分数组的问题
你之前考虑拆分front和back到两个数组,完全没必要。用对象数组(每个元素包含front和back)的方式更符合逻辑,后续维护时能清晰对应每张卡片的正反内容,不会混乱。
内容的提问来源于stack exchange,提问作者harry.exe
相关产品推荐
相关产品推荐

