Django Query to Aggregate the Sum for Matching Instances in the Same Field

流过昼夜 提交于 2021-02-19 02:34:35

问题


I have the following Django (2.1) model:

class Sales(models.Model):
    product_name = models.ForeignKey(Product)
    category = models.ForeignKey(Category)
    sales= models.DecimalField(max_digits=25)

I would like to receive the sum of all sales for each different product_name instance that is the same.

For example, I have the following sales by product_name:

  • DVDs = 6.00
  • DVDs = 6.00
  • Books = 14.00
  • Books = 6.00
  • Magazines = 4.00
  • Magazines = 4.00

I can use Sales.objects.aggregate(sales=Sum('sales')) to get the total aggregate of all sales instances combined but how can I get the aggregate for product_name separately; i.e. Books ($20.00), DVDs ($12.00), Magazines ($8.00)?


回答1:


We can use .annotate for this in combination with .values:

Sales.objects.values(
    'product_name'
).annotate(
    total_sales=Sum('sales')
).order_by('product_name')

Note that product_name is a ForeignKey, so we will get the id of the Product object, like:

<QuerySet [
    {'product_name': 1, 'total_sales': 12.00 },
    {'product_name': 2, 'total_sales': 20.00 },
    {'product_name': 3, 'total_sales': 8.00 } ]>

Therefore I think you are probably more interested in querying with the Product object instead, something like:

Product,objects.values(
    'name'
).annotate(
    total_sales=Sum('sales__sales')
).order_by('name')

Which then produces:

<QuerySet [
    {'name': 'Books', 'total_sales': 20.00 },
    {'name': 'DVDs', 'total_sales': 12.00 },
    {'name': 'Magazines', 'total_sales': 8.00 } ]>

These are thus QuerySets that contain dictionaries: each dictionary has two keys: 'name' and total_sales', and we can thus iterate over the dictionaries and process the key-value pairs.

We used total_sales since my experience is that naming the aggregate the same as another field typically results in some problems. First of all, it is not really clear that this is different from the sales field. Furthermore in some versions of Django this could result in invalid queries.

Note: since a ForeignKey refers to an object of the related model. I advise to rename product_name to just product.



来源:https://stackoverflow.com/questions/52339136/django-query-to-aggregate-the-sum-for-matching-instances-in-the-same-field

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!