Django + postgres:orderby + distinct + filter() - 奇怪的行为

时间:2017-04-12 19:21:48

标签: python django postgresql

我有2个简单的模型:Claim和ClaimStatus。声明可以有许多状态(例如:1:尚未分析,2:正在分析,3:已分析),所有这些状态都与claim_id和creation_date一起记录在数据库中。 这里感兴趣的模型 - ClaimStatus - 按以下方式创建:

class ClaimStatuss(models.Model):
    status =  models.IntegerField(choices=investigated_choices, default=1)
    claim_id = models.ForeignKey('Claim', to_field='claim_id')
    creation_date = models.DateTimeField(auto_now=True)

我的目标是选择声明及其最后(=活动)状态进行过滤以显示例如。所有正在分析的案例,使用此线程的建议: Django orm get latest for each group

为了简单起见,我的数据库中只有2个对象:

id: 6,claim_id: 578, status: 2, date: 2017-04-12 16:55:25.371014+00:00
id: 7,claim_id: 578, status: 3, date: 2017-04-12 17:04:06.944270+00:00

我执行以下操作:

  1. 选择所有ClaimStatuss对象,并将它们分组以使每个claim_id具有最新的一个(在此示例中只有一个):
  2. statuses = ClaimStatuss.objects.all().order_by('claim_id','-creation_date').distinct('claim_id')
    1. 我检查,如果只有一个,则为查询集选择了最新元素:
    2. statuses.get().status
          3
      1. 现在我过滤这个单元素Queryset,只留下包含status = 2
      2. 的对象
        statuses.filter(status=2).get().status
            2

        我看到,我的查询只包含一个状态为" 3"的对象,在过滤后还发现状态为" 2"!

        的对象

        我认为这是第一个命令的问题,但这是一个预期的行为(如果是这样,我做错了什么/我该怎么做才能使它工作)或一些错误?

        其他细节:

        检查状态= 3也带来了积极的结果(所有其他状态都没有)

        >>> statuses.filter(status=3).get().status
        3
        

        奇怪的是,我可以在statuses变量上执行get方法,它刚刚证明包含2个不同的对象:

        >>> statuses.get().status
        3
        

        ForeignKey不是问题 - 我尝试将其更改为String并且行为相同。

1 个答案:

答案 0 :(得分:1)

您对distinct()调用与过滤器其余部分之间的互动感到困惑。

所有distinct('claim_id)将确保返回每个声明中的一个项目。但你只要求一件物品;当您为status = 2添加过滤器时,您仍然只能获得claim_id的非重复值的一个项目。如果你没有添加过滤器,那就不一样了。