Django - 强制ManyToManyField唯一项
我想做一些简单的事情,比如这样:
members = models.ManyToManyField(User, blank=True, null=True, unique=True)
但是不允许设置唯一性。当我查看创建的表时,发现它生成了外键,所以我想唯一性是隐含的。
我想把成员和这个代表小组的模型关联起来。这个小组可以没有成员,但我不想让同一个成员能加入同一个小组两次。
我原本以为如果我尝试这样做会抛出一个异常,但似乎并没有抛出异常。
def join(request,id):
user = request.user
mygroup = Group.objects.get(id=id)
mygroup.members.add(user)
mygroup.num_members += 1
mygroup.save()
因为没有抛出异常,所以num_members在增加。重复的用户在管理工具中没有出现。难道add()
默默失败了吗?我是不是应该在添加之前先检查一下用户是否已经存在?
2 个回答
17
重复的用户在管理工具中不会出现。
因为这些用户根本没有被创建。
add() 方法会悄悄失败吗?
是的。
我是不是应该在添加用户之前先检查一下这个用户是否已经存在?
没错。或者,你也可以让数据库帮你统计用户数量,而不是自己手动去数:
mygroup = Group.objects.filter(...).annotate(num_members=models.Count("members"))
这样就不需要在模型里再加一个 num_members
字段了。
另外,你在函数里不应该用 id
作为参数名。
43
首先,我不建议使用 num_members
。你可以通过 mygroup.members.count()
来查看有多少个成员。其次,添加成员多次并不会真的重复添加,所以这点你不用担心。
在 Group
中使用 ManyToManyField
来指向 User
,实际上是通过一个单独的表来实现的(类似于 group_group_users
)。这个表里有指向 Group
和 User
的外键。一个用户可以加入多个小组,而一个小组也可以有多个用户,但在 group_group_users
表中,不能有两行记录表示同样的关系(也就是说,外键组合必须是唯一的)。
用法:
>>> group = Group.objects.get(pk=1)
>>> user = User.objects.get(pk=1)
>>> group.members.add(user)
>>> # Worked fine as expected. Let's check the results.
>>> group.members.all()
[<User: foousername>]
>>> group.members.add(user)
>>> # Worked fine again. Let's check for duplicates.
>>> group.members.all()
[<User: foousername>]
>>> # Worked fine.