如何查询ManyToMany字段以完全包含列表?

时间:2018-07-29 11:24:01

标签: django django-models django-views django-queryset

我的用户模型为:

User:
name

和一个房间:

Room:
users = ManyToManyField(User, related_name="rooms")

现在。我也有:

user_ids_list = [1,5],并且数据库中只有一个房间,只有这两个用户。

有一个用户实例,例如:

user1 = User.objects.get(pk=1)

因此,我可以将user1的所有房间设为:

user1.rooms.all()

但是,我需要找到ID为[1,5]的用户的房间。

我遇到了:user1.rooms.filter(users__id__in=[1,5]).exists() => True 但是,user1.rooms.filter(users__id__in=[1,23]).exists() => True也返回True。

好的。就像房间中是否存在列表中的任何一个。它返回True。但是,如果两个用户都没有空间,则返回False。我应该如何处理?

1 个答案:

答案 0 :(得分:1)

我们可以这样进行:首先用给定的User计数重叠的每个房间的user_ids个数量,然后检查该数量是否相等到2(或user_ids的长度,例如:

from django.db.models import Count, Q

user_ids = [1, 23]

Room.objects.annotate(
    nfilter=Count('users', filter=Q(users__id__in=user_ids))
    nusers=Count('users')
).filter(
    nusers=len(user_ids)
    nfilter=len(user_ids)
)

因此,我们首先为每个Room加上两个额外的数字:用户nusers的数量,然后是过滤的用户的数量,两者都必须等于user_ids中元素的数量,因为否则列表中并非所有用户都与会议室相关,或者会议室中有更多用户。

如果此查询集不为空(例如.exists()返回True,则存在这样的空间)。

  

注意:我们在此假设user_ids不同 id的集合。如果不是这种情况,则首先需要使用唯一性过滤器。