【问题标题】:Sum all values of database column with Queryset Model.objects.aggregate(Sum(***))使用 Queryset Model.objects.aggregate(Sum(***)) 对数据库列的所有值求和
【发布时间】:2013-06-15 11:09:57
【问题描述】:

所以我在 Django 中创建了一个费用表应用程序,并试图获得所有费用成本的总和,然后我想在我的模板中显示这些费用。

我的模特:

class Expense(models.Model):
    PAYMENT_CHOICES = (
      ('Cash', 'cash'), 
      ('Credit', 'credit'),
      ('Debit', 'debit')
    )
    date = models.DateField()
    store = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=20, decimal_places=2)
    payment_type = models.CharField(max_length=8, choices=PAYMENT_CHOICES)
    category = models.CharField(max_length=100)

    def __unicode__(self):
      return u'%s' % (self.date)

    def _price_sum(self):
      return self.objects.aggregate(total_price = Sum('price'))

    price_sum = property(_price_sum)

我正在尝试在我的模板中使用标签{{ expenses.price_sum }} 调用“price_sum”

我的模板是这样的

{% if expenses %}
<table class='table table-hover'>
<tr>
  <thead>
    <th>Date</th>
    <th>Store</th>
    <th>Price</th>
    <th>Payment Type</th>
    <th>Category</th>
    <th></th>
    <th></th>
  </thead>
</tr>
 {% for expense in expenses %}
<tr>
  <tbody>
    <td>{{expense.date}}</td>
    <td>{{expense.store}}</td>
    <td>${{expense.price|floatformat:"2"|intcomma}}</td>
    <td>{{expense.payment_type}}</td>
    <td>{{expense.category}}</td>
    <td>
      <form action='{{expense.id}}/' method='get'>
        <input type="submit" value="Edit" class="btn">
      </form></td>
    <td>
      <form action='{{expense.id}}/delete/' method='post'>{% csrf_token %}
        <input type="submit" value="Delete" class="btn btn-danger" data-dismiss="alert">
      </form></td>
  </tbody>
</tr>

{% endfor %}

</table>
<h3>Table: {{ expenses.price_sum }}</h3>
{% else %}
    <p>No expenses logged.</p>
{% endif %}

我不确定我是否错误地使用了模板标签,或者我的功能是否错误或出了什么问题。我知道这可能真的很简单,但我已经搜索了 StackOverflow 以及 Django 和 Python 文档以及我能找到的任何东西,但我就是想不通。

更新:views.py

from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from expenses.models import Expense
from expenses.form import ExpenseForm

def index(request,template='expenses/index.html'):
  all_expenses = Expense.objects.all()
  return render(request, template, {'all_expenses': all_expenses})

def new(request, template='expenses/new.html'):
  if request.method == 'POST':
    new_expense = ExpenseForm(request.POST)
    if new_expense.is_valid() and new_expense.clean():
      new_expense.save()
      return HttpResponseRedirect('/expenses/')
  else:
    new_expense = ExpenseForm()

  return render(request, template, {'new_expense':new_expense})

def edit(request, expense_id, template='expenses/edit.html'):
  expense = Expense.objects.get(id=expense_id)
  if request.method == 'POST':
    form = ExpenseForm(request.post, instance=expense)
    if form.is_valid and form.clean():
      expense = form.save()
      return HttpResponseRedirect('/expenses/')
    else:
      expense = ExpenseForm(instance=expense)

  return render(request, template, {'expense':expense})

def delete(request, expense_id):
  if request.method == 'POST':
    expense = Expense.objects.get(id=expense_id).delete()
    return HttpResponseRedirect('/expenses/')
  else:
    return HttpResponse(status=404)

【问题讨论】:

  • 我编辑了您帖子的标题。请不要使用标题来“标记”您的帖子,而是使用标记系统。这使人们更容易找到您的问题。

标签: python django django-models django-templates django-queryset


【解决方案1】:

aggregate 返回类似于{'total_price': Decimal('1234')} 的字典。

因此,将_price_sum 更改如下:

def _price_sum(self):
  return self.objects.aggregate(total_price=Sum('price'))['total_price']

或者,更改模板如下:

{{ expenses.price_sum.price_sum }}

【讨论】:

  • 我想知道我的模板标签是否也可能是一个问题,因为我尝试了您建议的两种方法,当我加载页面时没有任何显示,但是当我使用 shell 时,您建议的代码肯定工作。
  • @skscharr,您的视图不会将expenses 传递给模板。
  • 我知道这可能听起来很愚蠢,但我该怎么做呢?我真的被困住了:/
  • @skscharr, return render(request, template, {'expenses':expense})
【解决方案2】:

您没有说要在其中哪个视图中使用聚合(我想知道您为什么要发布所有这些视图)。但是,很明显,您永远不会在 任何 中传递 Expense 对象,并且由于 price_sum 是 Expense 上的实例方法,因此您将永远无法访问它。

但实际上你不想这样做。 price_sum 不应该是实例方法,因为它根本不会与实例交互。实际上,如果您尝试从 shell 运行该方法,您会看到以下错误:

AttributeError: Manager isn't accessible via Expense instances

这应该是不言自明的。

您应该定义一个自定义管理器并在那里定义一个 price_sum 方法,而不是这样做。然后你可以访问Expenses.objects.price_sum(),你可以在上下文中直接将它传递给你的模板。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    相关资源
    最近更新 更多