10👍
Django 3.0 introduced “distinct=True” on Sum and Avg:
https://docs.djangoproject.com/en/3.0/ref/models/querysets/#sum
21👍
From this answer for a related question:
from django.db.models import Sum
income_posts.values('category__name').order_by('category__name').annotate(total=Sum('amount'))
- [Django]-What is the purpose of apps.py in Django 1.9?
- [Django]-Uploading large files with Python/Django
- [Django]-Integrity error on django_admin_log after updating existing site to new Django 1.5 user model
13👍
Just to add to arjun27’s answer. Since that package seems to have been abandoned you might want to just copy past the 3 lines you need from it:
from django.db.models import Sum
class DistinctSum(Sum):
function = "SUM"
template = "%(function)s(DISTINCT %(expressions)s)"
Which can be used the same as above:
income_posts.annotate(total=DistinctSum('amount')
- [Django]-What does on_delete do on Django models?
- [Django]-Django admin listview Customize Column Name
- [Django]-Django model: NULLable field
9👍
I think this issue also related to Combining multiple aggregations.
Here is the ticket for this bug.
We can use Subquery
(Django Docs) to achieve this issue:
from django.db.models import Subquery, OuterRef, IntegerField, Sum, Value, Count
MyModel.objects.annotate(
count_model_a=Count('ModelA', distinct=True),
sum_model_b=Coalesce(
Subquery(
ModelB.objects.filter(
MyModel=OuterRef('pk')
).values('MyModel_id').annotate(
my_sum=Sum('MyModel_Field')
).values('my_sum')[:1],
output_field=IntegerField()
),
Value(0)
)
).values("count_model_a", "sum_model_b")
I also used Coalesce
(Django Docs) function to prevent returning None
.
The above code will run one query to DB.
- [Django]-Django migrations with multiple databases
- [Django]-How to do a HTTP DELETE request with Requests library
- [Django]-How to add multiple objects to ManyToMany relationship at once in Django ?
4👍
If you are on Postgres, you can use the django-pg-utils
package for sum of distinct values.
from pg_utils import DistinctSum
income_posts.annotate(total=DistinctSum('amount')
- [Django]-Django Model Fields Indexing
- [Django]-Write only, read only fields in django rest framework
- [Django]-Effects of changing Django's SECRET_KEY
2👍
For those who are using django 2.2 LTE, this behavior can be achieved just reproducing django 3.0 commit that implements distinct for Sum:
https://github.com/django/django/commit/5f24e7158e1d5a7e40fa0ae270639f6a171bb18e
this way:
from django.db.models Sum
class SumDistinctHACK(Sum):
allow_distinct = True
and now you can use the django 3.0 syntax:
queryset.annotate(
sum_result=SumDistinctHACK(
'relatedmodel__values_to_sum',
distinct=True,
)
)
remember to replace SumDistinctHACK
to Sum
if you upgrade to django >= 3.0
- [Django]-Keep Secret Keys Out
- [Django]-What's the best option to process credit card payments in Django?
- [Django]-Djangorestframework: Filtering in a related field
1👍
For older version of Django use Func
queryset.annotate(
sum_result=Sum(
Func(F('amount'), function='DISTINCT')
)
)
- [Django]-How to use Django's assertJSONEqual to verify response of view returning JsonResponse
- [Django]-How to insert data to django database from views.py file?
- [Django]-How to sign in with the Google+ API using Django?
0👍
You can do this:
income_posts.values("category__name").distinct().annotate(total=Sum("amount"))
- [Django]-Indexing JSONField in Django PostgreSQL
- [Django]-Django. You don't have permission to edit anything
- [Django]-How can I get the file name from request.FILES?