注释不同的 Django 查询集不再使用不同的查询集

Posted

技术标签:

【中文标题】注释不同的 Django 查询集不再使用不同的查询集【英文标题】:Annotating on a distinct Django Queryset is no longer using the distinct queryset 【发布时间】:2022-01-23 07:26:55 【问题描述】:

我有一个查询,我正在尝试注释字段 tail_tip 的每个值的计数。我的原始查询过滤了相关表,因此有必要使用 distinct()。 我不完全确定如何描述,但是当我注释不同的查询时,查询不再不同。这是我在 shell 中使用的查询。

// Without distinct()
Ski.objects.filter(published=True, size__size__in=[178, 179, 180, 181, 182, 183, 184]).count()
// 318

skis = Ski.objects.filter(published=True, size__size__in=[178, 179, 180, 181, 182, 183, 184]).distinct()
skis.count()   
// 297

skis.values('tail_tip').order_by('tail_tip').annotate(count=Count('tail_tip'))
// <QuerySet ['tail_tip': 'flat', 'count': 99, 'tail_tip': 'full_twin', 'count': 44, 'tail_tip': 'partial_twin', 'count': 175]>
// total count = 318

鉴于skis 已经是distinct() 我不知道为什么当我对其进行注释时,总计数等于非明确查询。

【问题讨论】:

【参考方案1】:

尝试添加distinct=True

skis.values('tail_tip').order_by('tail_tip').annotate(count=Count('tail_tip', distinct=True))

【讨论】:

&lt;QuerySet ['tail_tip': 'flat', 'count': 1, 'tail_tip': 'full_twin', 'count': 1, 'tail_tip': 'partial_twin', 'count': 1]&gt; 中添加不同的结果【参考方案2】:

假设名为SizeSki 的相关表具有一对多的关系。这可以通过这种方式完成:

ski_filtered = Ski.objects.filter(
    published=True, 
    id__in=Size.objects.values("skis__id").filter(  # Maybe somethig else than `skis` here, you didn't show its model, so I couldn't know
        size__in=[178, 179, 180, 181, 182, 183, 184]
    )
)

skis.values('tail_tip').distinct().order_by('tail_tip').annotate(count=Count('tail_tip'))

为什么会这样:DISTINCT 不能与 annotate() 一起使用。在 django 中实现 annotate() 是用它自己的 GROUP BY 子句实现的。所以在已经 GROUP BY-ed 的查询上应用 distinct() 是行不通的。

【讨论】:

这很有效,感谢您的解释!

以上是关于注释不同的 Django 查询集不再使用不同的查询集的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 中使用两个以不同方式格式化的查询集进行分页

使用 django 查询集访问不同的外键关系

Django 使用注释更新查询集

Django - 查询:使用相关模型字段注释查询集

Django 使用某些字段的最新值注释查询集

根据条件使用 ForeignKey Counts 注释 Django 查询集