列出唯一的M2M对象

时间:2017-02-25 18:30:00

标签: python django

我的Person模型有ManyToManyTags。 我试图获取所有标记组合,并列出具有唯一这些标记的人。

E.g:

Tags a b c d
Person 1 has tags a and b
Person 2 has tags a
Person 3 has tags c
Person 4 has tags a b and c

我想要的是:

Tag A: Person 2
Tag B: None
Tag C: Person 3
Tag D: None
Tags [A, B]: Person 1
Tags [A, C]: None
Tags [A, D]: None
Tags [B, C]: None
Tags [B, D]: None
Tags [C, D]: None
Tags [A, B, C]: Person 4
Tags [A, B, D]: None
(etc.)

使用itertools.combinations我可以迭代所有代码,例如:

for L in range(0, len(tag_list)+1):
    for tag_combination in combinations(tag_list, L):
        print(Person.objects.filter(tag__name__in=tag_list))

但上述问题(在print()声明中)是人4将弹出"标签A","标签B",标签C&# 34;,"标签[A,B]","标签[A,C]","标签[B,C]",&# 34;标签[B,D]","标签[C,D]","标签[A,B,C]"等等,而我只希望此人列在"标签[A,B,C]"。

知道如何最好地接近这个吗?

1 个答案:

答案 0 :(得分:0)

您可以直接查询M2M表并在人员和标签之间建立映射:

from collections import defaultdict

people_to_tags = defaultdict(list)

for tag_id, person_id in Person.tags.through.objects.all().values_list('tag_id', 'person_id'):
    people_to_tags[person_id].append(tag_id)

然后,只需反映映射:

tags_to_people = defaultdict(list)

for person_id, tags in people_to_tags.items():
    tags_to_people[tuple(tags)].append(person_id)

您只需要人数为1的行:

tag_to_person = {tag_id: people[0] for tag_id, people in tags_to_people.items() if len(people) == 1}