问题
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
ForeignKeyrefers to an object of the related model. I advise to renameproduct_nameto justproduct.
来源:https://stackoverflow.com/questions/52339136/django-query-to-aggregate-the-sum-for-matching-instances-in-the-same-field