Django如何用count注释多方字段

时间:2019-11-27 13:35:55

标签: django annotations

考虑以下内容:

class ModelA(models.Model):
    pass

class ModelB(models.Model):
    model_as = models.ManyToManyField(ModelA, db_index=True, related_name="model_bs", blank=True)


model_bs = model_a_object.model_bs.all()
for model_b in model_bs:
    print(model_b.model_as.count())
3
2

到目前为止,一切都很好。但是我想根据model_bs的数量创建model_as的有序列表。我的理解是,这应该可以解决问题:

model_bs = model_a_object.model_bs.all().annotate(count=Count("model_as")).order_by('count')

由于某些原因无法正常工作。当我打印进行检查时,带注释的count是错误的!

for model_b in model_bs:
    print(model_b.model_as.count(), model_b.count)
3 1
2 1

我做错了什么?这是print(model_bs.query)的sql输出:

SELECT "mobile_modelb"."id",
       "mobile_modelb"."modelb",
       COUNT(DISTINCT "mobile_modelb_model_as"."modela_id") AS "count"
FROM "mobile_modelb"
INNER JOIN "mobile_modelb_model_as" ON ("mobile_modelb"."id" = "mobile_modelb_model_as"."modelb_id")
WHERE "mobile_modelb_model_as"."modela_id" = 7
GROUP BY "mobile_modelb"."id"
ORDER BY "count" ASC

1 个答案:

答案 0 :(得分:1)

尝试将distinct=True添加到计数中。

model_bs = model_a_object.model_bs.all().annotate(
    count=Count("model_as", distinct=True)
).order_by('count')

编辑:

问题是因为您使用的是model_a_object.model_bs.all(),所以生成了此WHERE子句:

WHERE "mobile_modelb_model_as"."modela_id" = 7

解决方法可能是:

ModelB.objects.annotate(
    count=Count("model_as")
).filter(model_as=model_object_a)

如果这不起作用,请尝试在values()之前使用filter()来正确定义GROUP BY。

ModelB.objects.annotate(
    count=Count("model_as")
).values('id', 'count').filter(model_as=model_object_a)