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

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

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

  1. class Transaction(models.Model):
  2. user = models.ForeignKey(User, on_delete=models.CASCADE)
  3. TRANSACTION_CHOICES = [
  4. ('Expense','Expense'),
  5. ('Income','Income'),
  6. ]
  7. transaction_type = models.CharField(max_length=10, blank=False, choices=TRANSACTION_CHOICES, default="Expense",null=True)
  8. title = models.CharField(blank = False, max_length=30)
  9. description = models.CharField(blank = True, max_length=200)
  10. amount = models.DecimalField(blank=False, max_digits=10, decimal_places=2)
  11. date_paid = models.DateField(auto_now_add=False, blank=True, null=True)
  12. time_paid = models.TimeField(auto_now_add=False, blank=True, null=True)
  13. CATEGORY_CHOICES = [
  14. ('Groceries', 'Groceries'),
  15. ('Salary', 'Salary'),
  16. ('Bills', 'Bills'),
  17. ('Rent', 'Rent'),
  18. ('Gym', 'Gym'),
  19. ('Restaurant', 'Restaurant'),
  20. ('Vacation', 'Vacation'),
  21. ('Travel', 'Travel'),
  22. ('Gift', 'Gift'),
  23. ('Investments', 'Investments'),
  24. ('Savings', 'Savings'),
  25. ('Entertainment', 'Entertainment'),
  26. ('Internet', 'Internet'),
  27. ('Healthcare', 'Healthcare'),
  28. ('Lifestyle', 'Lifestyle'),
  29. ('Insurance', 'Insurance'),
  30. ('Other', 'Other'),
  31. ]
  32. category = models.CharField(max_length=50, blank=False, choices=CATEGORY_CHOICES)
  33. receipt = models.ImageField(upload_to='receipt_images', blank = True)
  34. def __str__(self):
  35. return self.title
  36. def receipt_url(self):
  37. if self.receipt and hasattr(self.receipt, 'url'):
  38. return self.receipt.url

views.py

  1. def expense_structure(request):
  2. #qs = Transaction.objects.values('category').annotate(total_amount=Sum('amount')).order_by('category')
  3. # Retrieve user's transactions
  4. transactions = Transaction.objects.filter(user=request.user).order_by('date_paid')
  5. # Extract data for graph
  6. labels = []
  7. data = []
  8. expense = 0
  9. for transaction in transactions:
  10. labels.append(transaction.date_paid.strftime("%m/%d/%Y"))
  11. if transaction.transaction_type == "Expense":
  12. expense = transaction.amount
  13. else:
  14. expense != transaction.amount
  15. data.append(expense)
  16. # Create chart data
  17. return JsonResponse(data={
  18. 'labels': labels,
  19. 'data': data,
  20. })

expense_structure.html

  1. {% extends 'base_content.html' %}
  2. {% block content %}
  3. <div class="col-sm-4 text-center my-3">
  4. <div class="card">
  5. <div class="card-header">
  6. <h4 class="card-title">Expense Structure</h4>
  7. </div>
  8. <canvas id="expense_structure" data-url="{% url 'expense_structure' %}"></canvas>
  9. <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script>
  10. <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  11. <script>
  12. $(function () {
  13. var $expense_structure = $("#expense_structure");
  14. $.ajax({
  15. url: $expense_structure.data("url"),
  16. success: function (data) {
  17. var ctx = $expense_structure[0].getContext("2d");
  18. new Chart(ctx, {
  19. type: 'bar',
  20. data: {
  21. labels: data.labels,
  22. datasets: [{
  23. label: 'Expenses',
  24. backgroundColor: 'blue',
  25. data: data.data
  26. }]
  27. },
  28. options: {
  29. responsive: true,
  30. legend: {
  31. position: 'top',
  32. },
  33. title: {
  34. display: true,
  35. text: 'Expense Structure Bar Chart'
  36. }
  37. }
  38. });
  39. }
  40. });
  41. });
  42. </script>
  43. </div>
  44. {% endblock %}
m528fe3b

m528fe3b1#

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

  1. class ExpenseStructureView(TemplateView):
  2. template_name = 'expense_structure.html'
  3. def get_context_data(self, **kwargs):
  4. context = super().get_context_data(**kwargs)
  5. qs = Transaction.objects.values('category').annotate(total_amount=Sum('amount')).order_by('category')
  6. context["categories"] = [d['category'] for d in qs]
  7. context["totals"] = [d['total_amount'] for d in qs]
  8. return context

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

  1. {% extends 'base_content.html' %}
  2. {% block content %}
  3. <h1>Expense Structure!</h1>
  4. <script>
  5. // jquery function
  6. $(document).ready(function(){
  7. var ctx = document.getElementById('myChart').getContext('2d');
  8. var myChart = new Chart(ctx, {
  9. type: 'doughnut',
  10. data: {
  11. labels: {{ categories|safe }},
  12. datasets: [{
  13. label: 'Expense',
  14. data: {{ totals|safe }},
  15. backgroundColor: [
  16. 'rgba(255, 99, 132, 0.2)',
  17. 'rgba(54, 162, 235, 0.2)',
  18. 'rgba(255, 206, 86, 0.2)',
  19. 'rgba(75, 192, 192, 0.2)',
  20. 'rgba(153, 102, 255, 0.2)',
  21. 'rgba(255, 159, 64, 0.2)'
  22. ],
  23. borderColor: [
  24. 'rgba(255, 99, 132, 1)',
  25. 'rgba(54, 162, 235, 1)',
  26. 'rgba(255, 206, 86, 1)',
  27. 'rgba(75, 192, 192, 1)',
  28. 'rgba(153, 102, 255, 1)',
  29. 'rgba(255, 159, 64, 1)'
  30. ],
  31. borderWidth: 1
  32. }]
  33. },
  34. options: {
  35. scales: {
  36. y: {
  37. beginAtZero: true
  38. }
  39. }
  40. }
  41. });
  42. });
  43. </script>
  44. <canvas id="myChart" width="400"
  45. height="100"></canvas>
  46. {% endblock %}
展开查看全部

相关问题