Django and Aggregate: Sum of distinct values?

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.


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')

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'))