如何计算Djang同一模型中两个m2m关系的相关实体数

2024-05-16 09:46:55 发布

您现在位置:Python中文网/ 问答频道 /正文

大致考虑到这两种模式:

class Person(models.Model):

    name = models.CharField()


class Resource(models.Model):

    people_contributing = models.ManyToManyField(
        Person, 
        related_name='resouces_contributing_to'
    )

    people_involved = models.ManyToManyField(
        Person, 
        related_name='resources_involved_in'
    )

对于所有人,我想得到他/她为贡献或参与的资源的数量。你知道吗

我尝试了以下方法:

resources = Resource.objects.all()

participations = Person.objects.filter(
    Q(resources_contributing_to__in=resources) |
    Q(resources_involved_in__in=resources)
).values(
    # group results by person
    'pk'
).annotate(
    count=Count('id')
).values_list(
    'pk',
    'name',
    'count'
).order_by('-count')

print(participations)

这给了我一个元组列表如下:

[
    # (id, name, count)
    (1, 'John Doe', 12),
    (2, 'Jane Doe', 5),
    (3, 'Donald Trump', 3),
]

但是,如果一个人既有贡献又有参与,则资源将被计数两次,因为该资源将两次加入到person表中。我想要的是,如果资源在两个关系中都存在,那么它只能被计数一次。你知道吗

如何更改查询集以防止出现这种情况?

我使用的是postgresql和django1.11。你知道吗


Tags: nameinmodelmodelscount资源peopleresource
1条回答
网友
1楼 · 发布于 2024-05-16 09:46:55

计算出现在任一关系中的条目可以通过计算第一个关系中的条目+计算第二个关系中的条目-计算两个关系中的条目来实现。可通过以下查询集在Django实现:

participations = Person.objects.filter(
    Q(resources_contributing_to__in=resources) |
    Q(resources_involved_in__in=resources)
).annotate(
    count=Count('resouces_contributing_to__id', distinct=True) + Count('resources_involved_in__id', distinct=True) - Count(Case(When(resources_involved_in__id=F('resouces_contributing_to__id'), then='resources_involved_in__id')), distinct=True),
).values_list(
    'pk',
    'name',
    'count'
).order_by('-count')

相关问题 更多 >