You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 05:53:16