在Django中使用Chart.js绘制支出结构饼图遇问题求助
问题解决方案
1. 修复按支出类别汇总金额的视图逻辑
当前视图未按类别做金额汇总,还存在无效代码(expense != transaction.amount无法正确排除收入项),替换为以下代码实现按支出类别统计总金额:
from django.db.models import Sum from django.http import JsonResponse from django.contrib.auth.decorators import login_required @login_required # 确保仅登录用户可访问 def expense_structure(request): # 过滤当前用户的支出记录,按类别汇总金额 expense_summary = Transaction.objects.filter( user=request.user, transaction_type='Expense' ).values('category').annotate(total_amount=Sum('amount')).order_by('-total_amount') # 提取类别名称和对应总金额(Decimal转float适配Chart.js) labels = [item['category'] for item in expense_summary] data = [float(item['total_amount']) for item in expense_summary] return JsonResponse({ 'labels': labels, 'data': data, })
2. 修复模板图表渲染问题
当前模板是柱状图配置,且存在JS语法错误,修改为饼图并优化交互:
{% extends 'base_content.html' %} {% block content %} <div class="col-sm-6 text-center my-3"> <div class="card"> <div class="card-header"> <h4 class="card-title">Expense Structure</h4> </div> <canvas id="expense_structure" data-url="{% url 'expense_structure' %}"></canvas> <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script> <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> <script> $(function () { var $expenseChart = $("#expense_structure"); $.ajax({ url: $expenseChart.data("url"), success: function (res) { // 处理无支出数据的情况 if (res.labels.length === 0) { $expenseChart.parent().append('<p>No expense data available</p>'); return; } var ctx = $expenseChart[0].getContext("2d"); // 为每个类别生成随机颜色 var bgColors = res.labels.map(() => { const r = Math.floor(Math.random() * 255); const g = Math.floor(Math.random() * 255); const b = Math.floor(Math.random() * 255); return `rgba(${r}, ${g}, ${b}, 0.6)`; }); new Chart(ctx, { type: 'pie', data: { labels: res.labels, datasets: [{ label: 'Total Expense', backgroundColor: bgColors, data: res.data }] }, options: { responsive: true, legend: { position: 'bottom', }, title: { display: true, text: 'Expense Category Distribution' }, tooltips: { // 显示金额占比 callbacks: { label: function(item, data) { const total = data.data.reduce((a, b) => a + b, 0); const percent = ((data.data[item.index] / total) * 100).toFixed(1); return `${data.labels[item.index]}: $${data.data[item.index]} (${percent}%)`; } } } } }); }, error: function() { $expenseChart.parent().append('<p>Failed to load expense data</p>'); } }); }); </script> </div> </div> {% endblock %}
3. 必要的配置检查
- 确保URL路由已正确映射视图:
# urls.py from django.urls import path from . import views urlpatterns = [ # 其他路由 path('expense-structure/', views.expense_structure, name='expense_structure'), ]
内容的提问来源于stack exchange,提问作者Jae
相关产品推荐
相关产品推荐

