Django Group By所有组合的ManyToManyField



我想对ManyToManyFieldhabit_type = models.ManyToManyField(HabitType, blank=True)执行group_by,但不是对每个现有元素,而是对现有排列。例如,目前有7个现有的元素被引用,下面的查询按每个元素分组。我想按照现有的排列进行分组比如(1,2)(1,3,5)(1,4,6,7)但是我不想要所有可能的组合,那就有点太多了。

result = obj.registration_set.values(habit_type=F('participantpersonal__habit_type'))
.annotate(number_personal=Coalesce(Count('participantpersonal__habit_type'), 0))
return result

例如,我有6个条目,习惯为(1,2),当前输出为:

{
"habit_type": 1,
"number_personal": 6
},
{
"habit_type": 2,
"number_personal": 6
}

和我希望的输出是:

{
"habit_type": [1,2],
"number_personal": 6
},

事先感谢您的帮助

我的问题的答案是相当复杂的,所以我在这里提供我自己的解决方案,这样也许其他人可以过滤数组:

首先收集所有可能的组合,我编写了helper方法,它返回给定范围内的所有组合。在本例中,范围为1到7,总共有127种组合:

def distinct_combinations(num_range):
result = []
for r in num_range:
comb = list(combinations(num_range, r))
result.append(comb)
return [item for sublist in result for item in sublist]

对于查询,我遍历每个组合,对于每个组合,我计算一个计数器列表(不知道它的确切术语),它计算所有id减去当前使用组合中的id。

查询本身的工作原理类似于过滤当前组合,然后排除计数器列表。例如,当字段有(1,)时,它不会被组合(1,2)匹配,因为2是计数器列表的一部分。由于仍然可以对条目进行多次计数,因此结果的id将被保存并用于排除的下一个查询。结果保存在自定义JSON中。

habit_types = list(HabitType.objects.values_list('id', flat=True))
all_combination = distinct_combinations(habit_types)
result = []
list_id = []
ids = list(obj.registration_set.values_list('id', flat=True))
total_participants = ParticipantPersonal.objects.filter(registration__in=ids)
for combination in all_combination:
comb_opposite = list([elem for elem in habit_types if elem not in combination])
num_pariticpants = total_participants.filter(habit_type=combination) 
.exclude(eat_habit_type__in=comb_opposite).exclude(id__in=list_id).values_list('id', flat=True)
list_id.extend(num_pariticpants)
num_result = num_pariticpants.count()
json = {
'habit_type': EatHabitType.objects.filter(id__in=combination).values_list('name', flat=True),
'num_participants': num_result
}
result.append(json)
return result

最新更新