如何使用相关对象的计数来注释我的 Django 查询集

问题描述 投票:0回答:1

我有 3 个 django 模型;

Machine
Component
Part

我正在尝试注释机器查询集以包含该机器中使用的唯一部件的数量。

在下面的示例中,ps1 用于制作

f1
ps1
ps2
用于制作
f2
f1
f2
用于制作
r1
。因此,使用 2 个独特的部分来创建
r1
,这是我想用来注释
r1
的值。到目前为止,我的代码在这种情况下输出 3。

    # |------------+---------------------+----------------+--------------+--------------|
    # | machine    | component           | part           | expected     | result       |
    # |            |                     |                | parts        | parts        |
    # |------------+---------------------+----------------+--------------+--------------|
    # | r1         | f1                  | ps1            | 2            | 3            |
    # |            | f2                  | ps1            |              |              |
    # |            |                     | ps2            |              |              |
    # |------------+---------------------+----------------+--------------+--------------|
  • Part
    ManyToManyField
    Component
  • Component
    ForeignKey
    Machine

这是我正在使用的函数来尝试完成此任务。

def annotate_machine_query_with_num_parts(machine_query):
    count_subquery = (
        Parts.objects.filter(pk=OuterRef("pk"))
        .annotate(count=Count("id", distinct=True))
        .values("count")
    )

    sum_subquery = (
        Parts.objects.filter(
            Q(component__machine_id=OuterRef("pk"))
        )
        .annotate(count=Subquery(count_subquery))
        .values("count")
        .annotate(num_parts=Sum("count"))
        .values("num_parts")
    )

    return machine_query.annotate(num_parts=Coalesce(sum_subquery, 0))

这适用于许多测试用例,但当一个部件被多个组件重复使用时会失败,就像这里的

ps1
的情况一样。

我尝试了一些导致

subquery must return a single row
错误的事情。我确信必须有一种更简单的方法来实现这一目标。

django postgresql django-queryset
1个回答
0
投票

我认为你把事情过于复杂化了。您可以与:

from django.db.models import Count

Machine.annotate(num_parts=Count('component__parts', distinct=True))
© www.soinside.com 2019 - 2024. All rights reserved.