使用Django与Chart.js实现按公司类型统计数量并展示饼图时无法显示饼图的问题排查
Django + Chart.js 饼图无法显示的问题排查与修复
问题背景
我需要统计CompanyType模型下各类型的公司数量并通过饼图展示,统计依据是Company表的name字段。已经完成了Django模型和视图的编写,但前端引入Chart.js后饼图始终无法显示,怀疑是前端脚本存在问题。
相关代码如下:
models.py
class CompanyType(models.Model): company_type = models.CharField(max_length=100) is_active = models.BooleanField(default=True) created_at = models.DateField(auto_now_add=True) updated_at = models.DateField(auto_now=True) class Company(models.Model): name = models.CharField(max_length=100) address = models.TextField() company_type = models.ForeignKey(CompanyType,on_delete=models.CASCADE) is_active = models.BooleanField(default=True)
views.py
def index(request): labels = [] data = [] queryset = Company.objects.values('company_type__company_type').annotate(company_type_sum=Count('name')).order_by('-company_type_sum') for entry in queryset: labels.append(entry['company_type__company_type']) data.append(entry['company_type_sum']) context = { 'labels':labels, 'data':data, } return render(request,'index.html',context)
index.html 脚本部分
<script> var ctx = document.getElementById('myChart').getContext('2d'); var myChart = new Chart(ctx, { type: 'pie', data: { labels: [data.labels], datasets: [{ label: 'Companies in Particular Section', data: [data.data], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: true } } } }); </script>
排查出的问题
- Django模板变量引用错误:在JS中直接写
[data.labels]是完全错误的,Django的上下文变量需要通过模板语法{{ }}输出,而且后端传递的labels和data本身已经是数组,不需要额外用[]包裹,否则会导致Chart.js拿到的是嵌套数组,无法正确解析。 - 饼图不需要坐标轴配置:你的
options里添加了scales配置,但饼图类型没有坐标轴,这个配置不仅多余,还可能干扰Chart.js的渲染逻辑。 - 缺少必要的Canvas元素:虽然你没提到,但如果页面上没有id为
myChart的<canvas>元素,JS会找不到渲染容器,饼图自然无法显示。
修复方案
1. 修正前端脚本中的变量引用和配置
修改index.html中的脚本部分,正确引用Django模板变量,并移除无用的坐标轴配置:
<!-- 首先确保页面上存在这个Canvas元素 --> <canvas id="myChart" width="400" height="400"></canvas> <script> var ctx = document.getElementById('myChart').getContext('2d'); var myChart = new Chart(ctx, { type: 'pie', data: { // 直接输出Django传递的数组,用|safe确保格式正确 labels: {{ labels|safe }}, datasets: [{ label: 'Companies in Particular Section', data: {{ data|safe }}, backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, // 移除scales配置,饼图不需要坐标轴 options: {} }); </script>
2. 可选优化:简化视图层代码
你的视图里手动遍历queryset组装labels和data可以简化,直接用Django的聚合结果来生成:
def index(request): queryset = Company.objects.values('company_type__company_type').annotate(count=Count('name')).order_by('-count') # 直接从queryset中提取数据,不需要手动循环 labels = [item['company_type__company_type'] for item in queryset] data = [item['count'] for item in queryset] context = { 'labels': labels, 'data': data, } return render(request, 'index.html', context)
验证步骤
- 启动Django服务,访问页面打开浏览器开发者工具(F12),查看Console面板是否有JS报错。
- 查看页面源码,确认
labels和data是否被正确渲染成数组格式(比如["医疗", "科技"]和[4, 6])。 - 确认Canvas元素存在且能被JS正确获取。
内容的提问来源于stack exchange,提问作者Ishan Khaire
相关产品推荐
相关产品推荐

