【问题标题】:Django annotation does not group output as intendedDjango 注释未按预期对输出进行分组
【发布时间】:2022-08-19 03:52:44
【问题描述】:

以下是我的模型:

class Project(models.Model):
     name = models.CharField(max_length=1000, null=True, blank=True)
     date_created = models.DateTimeField(auto_now=True)
     status = models.CharField(max_length=1000, null=True, blank=True)

状态字段有大约 5 个不同的选项(赢得、丢失、打开、待处理、已取消)。

我需要知道如何在给定的时间范围查询中获取每个月具有 x 状态的项目数量。

我能够使用以下注释获得正确的数据形状 - 但由于某种原因,给定的输出会为一个月内找到的每个状态提供一个对象。例如,如果在同一月份找到至少 1 个“Won”和 1 个“Open”项目,则同一月份将返回两个单独的对象。此外,此处的状态选项是硬编码的,如果添加了新状态,则需要对其进行修改。

queryset = list(opps.annotate(
    month=TruncMonth(\'date_created\'),
).values(\'month\').annotate(
    total=Count(\'id\'),
    Win=Count(\'id\', filter=Q(status=\'Win\')),
    Loss=Count(\'id\', filter=Q(status=\'Loss\')),
    Open=Count(\'id\', filter=Q(status=\'Open\')),
    Dormant=Count(\'id\', filter=Q(status=\'Dormant\')),
    Pending=Count(\'id\', filter=Q(status=\'Pending\')),
    Cancelled=Count(\'id\', filter=Q(status=\'Cancelled\')),
))

这是我当前输出的示例。

[{\'month\': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key=\'UTC\')), \'total\': 1, \'Win\': 0, \'Loss\': 1, \'Open\': 0, \'Dormant\': 0, \'Pending\': 0, \'Cancelled\': 0}
{\'month\': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key=\'UTC\')), \'total\': 1, \'Win\': 0, \'Loss\': 1, \'Open\': 0, \'Dormant\': 0, \'Pending\': 0, \'Cancelled\': 0}
{\'month\': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key=\'UTC\')), \'total\': 1, \'Win\': 0, \'Loss\': 0, \'Open\': 1, \'Dormant\': 0, \'Pending\': 0, \'Cancelled\': 0}
{\'month\': datetime.datetime(2022, 6, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key=\'UTC\')), \'total\': 1, \'Win\': 0, \'Loss\': 0, \'Open\': 1, \'Dormant\': 0, \'Pending\': 0, \'Cancelled\': 0}]

    标签: python django datetime annotate


    【解决方案1】:

    如果您的模型未通过 Meta 类定义排序,则必须在第二次 annotate 调用之前指定排序。

    queryset = list(opps
                    .annotate(month=TruncMonth('date_created'))
                    .order_by('month')  # <== this is necessary for the correct results
                    .values('month')
                    .annotate(total=Count('id'),
                              Win=Count('id', filter=Q(status='Win')),
                              Loss=Count('id', filter=Q(status='Loss')),
                              Open=Count('id', filter=Q(status='Open')),
                              Dormant=Count('id', filter=Q(status='Dormant')),
                              Pending=Count('id', filter=Q(status='Pending')),
                              Cancelled=Count('id', filter=Q(status='Cancelled'))))
    

    【讨论】:

      猜你喜欢
      • 2012-02-08
      • 2019-11-04
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 2011-04-02
      • 2017-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多