简体   繁体   中英

Django Annotate Sum

I'm trying to get a simple sum for a column with several rows in a queryset. My direct question is (a) how do I set get_queryset() to include a sum of a column and (b) how do I access that element in a template? Following this question:

#models.py
class ItemPrice( models.Model ):
    price = models.DecimalField ( max_digits = 8, decimal_places=2 )
    ....

There are two answers provided - one using the .aggregate() method which I don't believe returns a queryset and .annotate() method which I believe appends an item to the queryset.

So, I would have expected that the following would add another item to the object list in this view:

#views.py
def get_queryset(self):
    # generate table and filter down to a subquery.
    queryset = ItemPrice.objects.filter(<some_filter>)
    # sum the price for each row in the subquery.
    queryset = queryset.annotate(totals=Sum('price'))
    return queryset

Then in the the Template, I would be able to iterate through the object list like this:

#template.html
{% for item in object_list %}
    {{ item }}
{% endfor %}

With the expectation that one of the items (the last item?) would be price_sum and that the balance could be accessed as price_sum.price .

However, when i add the following to my template, I get the prices for each line item - no summation.

{% for item in object_list %}
    {{ item.totals }}
{% endfor %}

But, I can't access the item. I don't know if the problem is the view modification of the get_queryset() or if it's in the template?

if you would use:

ItemPrice.objects.filter(<some_filter>).annotate(totals=Sum('price'))

totals always will be the same as 'price'

annotate (about Sum) uses like this:

if you have these models:

class ItemPrice( models.Model ):
    price = models.DecimalField ( max_digits = 8, decimal_places=2 )
    other_model = models.ForeignKey(
          to=OtherModel, 
          related_name="item_prices", 
          on_delete=models.SET_NULL
    )

# related_name - if I set related_name I can use like this
# other_model_object.item_prices.all() - this code return all 
# ItemPrices with other_model_id=other_model_object.id

class OtherModel(models.Model):
    some_field = models.CharField(max_lenght=256)

and you want to all price of all ItemPrices which have foreign key to one OtherModel you should use these code:

queryset = OtherModel.objects.annotate(
       total_prices=Sum('item_prices__price')
).filter(<your_filters>)

after that you can use:

for obj in queryset:
    print(obj.total_prices)

Or if you need sum of all prices you should use aggregate

ItemPrices.objects.aggregate(all_sum=Sum('price'))

this code return dict(or something like that, I do not remember exactly) like this

{'all_sum': 1250}

all_sum - sum of all objects in your table in database

if you want to add data to the template

queryset = ItemPrice.objects.filter(<your_filter>)
totals = queryset.aggregate(sum=Sum('price').get('sum')

context  = {
    'object_list': queryset,
    'totals': totals,
}
render(request, '<name_of_your_template>.html', context)

and in your template

{% for item in object_list %}
    # price of item
    {{ item.price }}
{% endfor %}
# total price
{{ totals }}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM