在Django queryset中按月和性别分组

时间:2018-06-29 21:22:35

标签: django django-queryset django-orm

我有以下查询集,它与按月分组很好。

from django.db.models.functions import TruncMonth

queryset = UserProfile.objects.filter(date_created__year='2018')\
           .annotate(date=TruncMonth('date_created'))\
           .values('date').annotate(total_entries=Count('id'))

我想要的是也按性别分组,这是一个带有gender字段的类似模型

class UserProfile:
    date_created = models.DateTime(auto_now_add=True)
    gender = models.CharField(max_length=3,choices=[('F',"Female"),('M',"Male")],default='M')

预期结果:

May: 5 users [4(Male), 1(Female)]
June: 20 users [15(Male), 5(Female)]

1 个答案:

答案 0 :(得分:2)

对于django < 2.0,您可以使用Conditional ExpressionsSum()注释所需的值:

from django.db.models import Sum, Case, When
from django.db.models.functions import TruncMonth

queryset = UserProfile.objects.filter(date_created__year='2018').annotate(
    date=TruncMonth('date_created'),
).values('date').annotate(
    total_entries=Count('id'),
    total_male=Sum(Case(When(gender='M', then=1), default=0, output_field=models.IntegerField())),
    total_female=Sum(Case(When(gender='F', then=1), default=0, output_field=models.IntegerField())),
)

django 2.0起,您可以使用Conditional Aggregation

from django.db.models import Count, Q
from django.db.models.functions import TruncMonth

queryset = UserProfile.objects.filter(date_created__year='2018').annotate(
        date=TruncMonth('date_created'),
    ).values('date').annotate(
        total_entries=Count('id'),
        total_male=Count('id', filter=Q(gender='M')),
        total_female=Count('id', filter=Q(gender='F')),
)