使用Django ManyToManyField检查实例是否存在

使用Django ManyToManyField检查实例是否存在,django,django-queryset,django-orm,manytomanyfield,Django,Django Queryset,Django Orm,Manytomanyfield,大家好,真棒 如何使用ManyToManyField()检查数据库中是否已存在类似记录: 在我看来,在创建新房间之前,我想确保没有一个活动房间有完全相同的参与者。 下面的示例不起作用,它只是向您展示我的期望 我怎样才能继续做我想做的事?您不能创建这样一个包含多个字段的对象,因为该对象必须存在,然后才能创建表示m2m关系的中间对象。您必须执行以下操作: allowed_users = User.objects.filter(id__in=request.POST.get("ids", [])).o

大家好,真棒

如何使用
ManyToManyField()
检查数据库中是否已存在类似记录:

在我看来,在创建新房间之前,我想确保没有一个活动房间有完全相同的参与者。

下面的示例不起作用,它只是向您展示我的期望


我怎样才能继续做我想做的事?

您不能创建这样一个包含多个字段的对象,因为该对象必须存在,然后才能创建表示m2m关系的中间对象。您必须执行以下操作:

allowed_users = User.objects.filter(id__in=request.POST.get("ids", [])).order_by('id')

room = None
for r in up.rooms.filter(is_active=True):
    if list(allowed_users) == list(r.allowed_users.all().order_by('id')):
        room = r # get the existing room
        break

if not room:
    room = Room.objects.create(
        created_by = request.user,
        is_active = True
    )
    room.allowed_users.add(*allowed_users)
您必须确保允许的\u用户与room.allowed\u用户的顺序相同


有关详细信息,您不能创建具有多个字段的对象,因为该对象必须存在,才能创建表示m2m关系的中间对象。您必须执行以下操作:

allowed_users = User.objects.filter(id__in=request.POST.get("ids", [])).order_by('id')

room = None
for r in up.rooms.filter(is_active=True):
    if list(allowed_users) == list(r.allowed_users.all().order_by('id')):
        room = r # get the existing room
        break

if not room:
    room = Room.objects.create(
        created_by = request.user,
        is_active = True
    )
    room.allowed_users.add(*allowed_users)
您必须确保允许的\u用户与room.allowed\u用户的顺序相同


有关更多信息,请参见这是因为
allowed\u users
是一个
ManyToMany
字段,因此在向其中添加用户之前需要创建文件室

见此处的官方文件:

现在,另一个问题是我们需要一个拥有相同用户集的现有房间,这已经在这里的一个类似问题中得到了回答:

请尝试以下内容:

from django.db.models import Count

allowed_users = User.objects.filter(id__in=request.POST.get("ids",[]))
if allowed_users:
    room = Room.objects.filter(allowed_users__in=allowed_users).annotate(num_users=Count('allowed_users')).filter(num_users=len(allowed_users)).first()
    if not room:
        room = Room.objects.create(created_by=request.user, is_active=True)
        room.allowed_users.add(*allowed_users)

这是因为
allowed\u users
是一个
ManyToMany
字段,因此在向其中添加用户之前需要创建文件室

见此处的官方文件:

现在,另一个问题是我们需要一个拥有相同用户集的现有房间,这已经在这里的一个类似问题中得到了回答:

请尝试以下内容:

from django.db.models import Count

allowed_users = User.objects.filter(id__in=request.POST.get("ids",[]))
if allowed_users:
    room = Room.objects.filter(allowed_users__in=allowed_users).annotate(num_users=Count('allowed_users')).filter(num_users=len(allowed_users)).first()
    if not room:
        room = Room.objects.create(created_by=request.user, is_active=True)
        room.allowed_users.add(*allowed_users)


如果完成get_或_create,则有可能将允许的_用户添加到现有房间中。相反,如果不存在具有允许的\u用户的房间,则应创建一个新房间。我想检查是否没有具有完全相同参与者的活动房间,如果是,则获取房间而不是创建一个新房间
允许的\u用户
是一个查询集,而不是列表。。。这种比较是行不通的。但我得到了你的信任point@EuChi是的,也解决了订购问题。我认为这会起作用,但没有更好的方法来代替for循环??如果完成get_或_create,那么允许的_用户很可能会被添加到现有的房间中。相反,如果不存在具有允许的\u用户的房间,则应创建一个新房间。我想检查是否没有具有完全相同参与者的活动房间,如果是,则获取房间而不是创建一个新房间
允许的\u用户
是一个查询集,而不是列表。。。这种比较是行不通的。但我得到了你的信任point@EuChi是的,也解决了订购问题。我认为这会起作用,但没有更好的方法代替for loop??我想检查是否没有完全相同参与者的活动房间,如果是,则获取房间,而不是创建新房间one@EuChi明白了,修改了,这看起来很完美,您能解释一下您有
注释
计数
的部分吗
.annotate(num_users=Count('allowed_users'))。filter(num_users=len(allowed_users))
注释
用于
分组
操作,然后仅获取注释值,如
num_users
Count
用于通过操作从
group\U获取每个
组的计数。然后,
.filter(num\u users=len(allowed\u users)
将向查询中添加一个
having
子句。您可以通过在查询集Let
allowed\u users
=[1,2,3,4,5]上添加
len(allowed\u users)
来获得准确的SQL查询。然后
len(allowed\u users)
将是5个查询,如下所示:选择“房间”。.id”,计数(“房间用户”)。“user_id”)作为“num_users”从“rooms”左外部加入“rooms_users”在(“rooms”。“id”=“rooms_users”。“rooms_id”)其中(“rooms_users”。(1,2,3,4,5))组中的“user_id”由“rooms”。“id”具有计数(“rooms_users”。“user_id”)=5我想检查是否没有完全相同参与者的活动房间,如果是,则获取房间,而不是创建新房间one@EuChi明白了,修改它。这看起来很完美,你能解释一下你有
annotate
Count
..
.annotate(num\u users=Count('allowed\u users'))的部分吗。过滤器(num_users=len(allowed_users))
annotate
用于
group_by
操作,然后仅获取注释值,如
num_users
Count
用于通过
操作从
group_获取每个
组的计数。然后
.filter(num_users=len(allowed_users)
将向查询中添加一个
having
子句。您可以通过添加
来获得准确的SQL查询。在查询集上查询
allowed_users
=[1,2,3,4,5],然后
len(allowed_users)
将是5个查询,如下所示:从“房间”中选择“房间”,“id”,将(“房间用户”,“用户id”)计数为“num_用户”“左外连接(“房间”。“id”=“房间用户”。“房间id”)上的“房间用户”,其中(“房间用户”。(1,2,3,4,5))组中的“用户id”由“房间”。“id”具有计数(“房间用户”。“用户id”)=5”