如何在Django中将字典数据传递给Chart.js生成图表
Django + Chart.js 图表不显示问题修复方案
问题根源分析
你的代码存在以下几个核心问题:
- 模板中错误使用
data.keys/data.values,传递给JS的是数组而非单个分类名称/数量 - 分类名称作为字符串未加引号,导致JS语法解析错误
- 包含
category: null和count:0的无效数据,干扰图表渲染 - 颜色数组长度不足,部分分类无对应颜色
- 饼图(doughnut类型)不需要配置y轴刻度,多余配置引发冲突
- 可能缺少Chart.js和jQuery的依赖引入
分步修复代码
1. 优化视图查询(过滤无效数据)
修改视图中的get_context_data方法,过滤掉空分类和数量为0的无效记录:
class CategoryChartListView(generic.ListView): model = Book template_name= 'pages/chart_category.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 过滤空分类和数量为0的记录,同时可选合并大小写分类(比如python/Python) context["dictCategory"] = Book.objects.values('category')\ .annotate(count=Count('category'))\ .exclude(category__isnull=True)\ .exclude(count=0) return context
如果需要合并大小写分类,可使用Lower函数统一转换后分组,具体代码见文末额外建议
2. 修正模板数据传递与图表配置
替换模板中的脚本部分,修复数据传递逻辑并优化图表配置:
{%block content%} <canvas id="myChart" width="400" height="100"></canvas> {%endblock content%} {%block scripts%} <!-- 先加载依赖库,必须在自定义脚本之前 --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> $(document).ready(function(){ var ctx = document.getElementById('myChart').getContext('2d'); // 动态生成足够的颜色,避免分类过多时颜色不足 const generateColors = (count) => { const bgColors = []; const borderColors = []; for(let i=0; i<count; i++){ const r = Math.floor(Math.random()*255); const g = Math.floor(Math.random()*255); const b = Math.floor(Math.random()*255); bgColors.push(`rgba(${r}, ${g}, ${b}, 0.2)`); borderColors.push(`rgba(${r}, ${g}, ${b}, 1)`); } return {bgColors, borderColors}; }; // 从Django上下文提取有效数据 const labels = [{%for data in dictCategory%}"{{ data.category|escapejs }}", {%endfor%}].filter(Boolean); const counts = [{%for data in dictCategory%}{{ data.count }}, {%endfor%}].filter(Boolean); const {bgColors, borderColors} = generateColors(labels.length); var myChart = new Chart(ctx, { type: 'doughnut', data: { labels: labels, datasets: [{ label: '书籍数量', data: counts, backgroundColor: bgColors, borderColor: borderColors, borderWidth: 1 }] }, // 饼图不需要坐标轴配置,清空即可 options: {} }); }); </script> {%endblock scripts%}
关键修改点说明
- 数据传递修正:直接使用
data.category和data.count获取字段值,用|escapejs处理特殊字符,给字符串添加双引号确保JS正确解析 - 无效数据过滤:通过
filter(Boolean)移除空的标签和数据条目 - 颜色动态生成:根据分类数量自动生成对应颜色,避免颜色不足
- 依赖引入:添加Chart.js和jQuery的CDN链接,确保依赖加载完整
- 配置精简:移除饼图不需要的y轴刻度配置,避免冲突
额外建议:合并大小写分类
如果需要将python和Python这类大小写不同的分类合并,可修改视图代码:
from django.db.models.functions import Lower def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["dictCategory"] = Book.objects.annotate(lower_category=Lower('category'))\ .values('lower_category')\ .annotate(count=Count('lower_category'))\ .exclude(lower_category__isnull=True)\ .exclude(count=0) return context
模板中对应的标签改为data.lower_category即可。
内容的提问来源于stack exchange,提问作者mosleh azizi
相关产品推荐
相关产品推荐

