在Django中使用chart.js制作饼图错误

ndh0cuux  于 2023-03-12  发布在  Chart.js
关注(0)|答案(1)|浏览(160)

我正在构建一个预算跟踪器应用程序,在 Jmeter 板页面中,我想列出不同的图表。饼图是用于费用结构,显示在某些类别中花费了多少费用。我主要面临两个问题。第一个问题是视图中的模型数据没有通过结果图未显示的模板。第二个问题是我试图显示某些类别的费用比例。不是每项费用的一个比例(如果它们属于同一类别,则必须计算累积费用的总和)。如果我能得到帮助,我将不胜感激。
models.py

class Transaction(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
TRANSACTION_CHOICES = [
    ('Expense','Expense'),
    ('Income','Income'),
]
transaction_type = models.CharField(max_length=10, blank=False, choices=TRANSACTION_CHOICES, default="Expense",null=True)
title = models.CharField(blank = False, max_length=30)
description = models.CharField(blank = True, max_length=200)
amount = models.DecimalField(blank=False, max_digits=10, decimal_places=2)
date_paid = models.DateField(auto_now_add=False, blank=True, null=True)
time_paid = models.TimeField(auto_now_add=False, blank=True, null=True)

CATEGORY_CHOICES = [
('Groceries', 'Groceries'),
('Salary', 'Salary'),
('Bills', 'Bills'),
('Rent', 'Rent'),
('Gym', 'Gym'),
('Restaurant', 'Restaurant'),
('Vacation', 'Vacation'),
('Travel', 'Travel'),
('Gift', 'Gift'),
('Investments', 'Investments'),
('Savings', 'Savings'),
('Entertainment', 'Entertainment'),
('Internet', 'Internet'),
('Healthcare', 'Healthcare'),
('Lifestyle', 'Lifestyle'),
('Insurance', 'Insurance'),
('Other', 'Other'),
]
category = models.CharField(max_length=50, blank=False, choices=CATEGORY_CHOICES)
receipt = models.ImageField(upload_to='receipt_images', blank = True)

def __str__(self):
    return self.title

def receipt_url(self):
    if self.receipt and hasattr(self.receipt, 'url'):
        return self.receipt.url

views.py

def expense_structure(request):
#qs = Transaction.objects.values('category').annotate(total_amount=Sum('amount')).order_by('category')

# Retrieve user's transactions
transactions = Transaction.objects.filter(user=request.user).order_by('date_paid')
# Extract data for graph
labels = []
data = []
expense = 0
for transaction in transactions:
    labels.append(transaction.date_paid.strftime("%m/%d/%Y"))
    if transaction.transaction_type == "Expense":
        expense = transaction.amount
    else:
        expense != transaction.amount
    data.append(expense)
# Create chart data
return JsonResponse(data={
    'labels': labels,
    'data': data,
})

expense_structure.html

{% extends 'base_content.html' %}
{% block content %}
<div class="col-sm-4 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 $expense_structure = $("#expense_structure");
                    $.ajax({
                        url: $expense_structure.data("url"),
                        success: function (data) {
                            var ctx = $expense_structure[0].getContext("2d");
                            new Chart(ctx, {
                                type: 'bar',
                                data: {
                                labels: data.labels,
                                datasets: [{
                                    label: 'Expenses',
                                    backgroundColor: 'blue',
                                    data: data.data
                                }]          
                                },
                                options: {
                                responsive: true,
                                legend: {
                                    position: 'top',
                                },
                                title: {
                                    display: true,
                                    text: 'Expense Structure Bar Chart'
                                }
                                }
                            });

                            }
                        });

                        });

             </script>
 </div>

{% endblock %}
m528fe3b

m528fe3b1#

您试图将整个查询集传递给图表数据,但需要按类别对事务进行分组,并对每个类别的金额求和,以显示每个类别下的费用比例。
使用以下代码更新ExpenseStructureView类:

class ExpenseStructureView(TemplateView):
template_name = 'expense_structure.html'

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    qs = Transaction.objects.values('category').annotate(total_amount=Sum('amount')).order_by('category')
    context["categories"] = [d['category'] for d in qs]
    context["totals"] = [d['total_amount'] for d in qs]
    return context

代码已更新为按类别对交易进行分组,并对每个类别的金额求和,然后将结果数据传递到模板中的图表。
在此之后,您需要更新您的expense_structure.html模板文件如下:

{% extends 'base_content.html' %}
{% block content %}
<h1>Expense Structure!</h1>
<script>
    // jquery function
    $(document).ready(function(){
        var ctx = document.getElementById('myChart').getContext('2d');
        var myChart = new Chart(ctx, {
            type: 'doughnut',
            data: {
                labels: {{ categories|safe }},
                datasets: [{
                    label: 'Expense',
                    data: {{ totals|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
                }]
            },
            options: {
                scales: {
                    y: {
                        beginAtZero: true
                    }
                }
            }
});
    });
</script>

<canvas id="myChart" width="400" 
height="100"></canvas>
{% endblock %}

相关问题