我有 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
错误的事情。我确信必须有一种更简单的方法来实现这一目标。
我认为你把事情过于复杂化了。您可以与:
from django.db.models import Count
Machine.annotate(num_parts=Count('component__parts', distinct=True))