我对遗留数据库感到困惑。我想修改默认查询集以便熟练地使用db,为此我需要使用GROUP BY
。我知道我可以做到这一点,让我得到我想要的SQL:
query = Variant.objects.all().query
query.group_by = ['name']
return QuerySet(query=query, model=Variant)
这将导致我追求的查询集。所以我构建了一个queryset Manager来帮助我。问题是它正在返回正确的值,但是当我指望它时,它是错误的。
class VariantQuerySet(QuerySet):
def group_by_name(self):
self.query.group_by = ['name']
return self.filter()
class VariantManager(models.Manager):
def get_query_set(self):
return VariantQuerySet(self.model, using=self._db)
但是当我开始玩它时..
>>> Variant.objects.filter(project__name__icontains="zam")
[<Variant: RevA>, <Variant: RevA>, <Variant: RevA>, <Variant: revB>, <Variant: RevC_Fiendish>, <Variant: RevA>, <Variant: RevA_tapeout>]
>>> Variant.objects.filter(project__name__icontains="zam").count()
7
>>> Variant.objects.filter(project__name__icontains="zam").group_by_name()
[<Variant: RevA>, <Variant: revB>, <Variant: RevC_Fiendish>, <Variant: RevA_tapeout>]
到目前为止一切顺利。 7个未分组的项目,4个分组。
>>> Variant.objects.filter(project__name__icontains="zam").group_by_name().count()
7
那么为什么我的计数仍然停留在7 - 它应该是4?我认为_result_cache持有该值,所以我在方法中将其设置为None但没有运气。任何想法为什么这是错误的?
答案 0 :(得分:1)
.count()
实际创建了一个新查询,删除了字段并替换为COUNT(*)
。实际上不可能按字段进行分组,而在纯SQL中对分组表进行计数。基本上,您最初的查询在SQL中看起来像这样:
SELECT myapp_variant.id, myapp_variant.name, myapp_variant.etc, ...
FROM myapp_variant inner join myapp_project on myapp_variant.project_id = myapp_project.id
WHERE myapp_project.name='zam'
GROUP BY myapp_variant.name
计数查询看起来像这样:
SELECT COUNT(*)
FROM myapp_variant inner join myapp_project on myapp_variant.project_id = myapp_project.id
WHERE myapp_project.name='zam'
请注意,它不能再分组。如果确实如此,您将得到以下结果集:
COUNT
-----
4
1
1
1
(在这种情况下,4是RevA记录的数量,然后是其他每个记录的1)
因为当您在聚合查询中 group 时,您告诉SQL为每个分组列中的每个唯一值创建一行。 4种不同的变体名称,所以4条记录!这根本不是你想要的
您可以通过输出Django生成的查询来确认这是否是这个问题:
>>> print Variant.objects.filter(project__name__icontains="zam").group_by_name().query
>>> print Variant.objects.filter(project__name__icontains="zam").group_by_name().count().query
这个问题实际上只有两个解决方案:
当您需要对分组查询集进行“计数”时,只需使用len()
,而不是
len(Variant.objects.filter(project__name__icontains="zam").group_by_name())
或者,在模板中:
{{ grouped_variants|length }}