gpt4 book ai didi

python - Django 对 ManyToManyField 中的成员集实现唯一约束

转载 作者:太空宇宙 更新时间:2023-11-04 04:57:53 24 4
gpt4 key购买 nike

我在 Django 中工作,但在对我的数据模型实现特定约束时遇到了一些问题。我有一个由一组成员组成的模型。

class Member:
name = models.CharField(max_length=100)

class Team:
members = models.ManyToManyField(Member)

我想强制执行一个约束,使得对于任何给定的团队,成员集都是唯一的。也就是说,允许以下团队:

team_a: {A, B, C}
team_b: {A, B, D}

但是 team_c: {C, B, A} 是不允许的,因为成员集与 team_a 相同。

如果我尝试添加 team_c(或具有相同成员集的任何其他团队),我如何强制执行此约束以抛出错误?

我考虑过为每个成员设置一个外键,然后使用 unique_together,但这行不通,因为我希望模型不知道成员内的顺序(因为有数据中没有固有的顺序)。我认为这可能是 the m2m_changed signal 的工作,但我无法让它正常工作。

最佳答案

嗯,没有直接的方法,但在我的头脑中这可能有效。

只有当您要添加的成员存在于其他团队中时,一组成员与另一个团队成员发生冲突的唯一可能性,因此首先我们需要获取那些已添加用户的团队:

# fetch teams where user is already added
teams = Team.objects.filter(members__id=user.id)

will_clash = False
if teams:
# prepare list of tuples of sorted members id for each team
members_set = [tuple(team.members.values_list('id', flat=True).order_by('id')) for team in teams]

# we know already in which team we want to add lets say it is `team_c`
team_c_members_set = tuple(sorted(list(team_c.members.values_list('id', flat=True)) + [user.id]))

if team_c_members_set in members_set:
# adding current `user` is going to create a clash
will_clash = True

if not will_clash:
# all good lets add the user in team
team_c.members.add(user)

试运行:

假设您有以下三个团队:

    Team A:
1: member
2: member
3: member

Team B:
1: member
2: member
4: member

Team C:
3: member
2: member

现在我们要将成员 id: 1 添加到团队 C 中。应该避免这种情况,因为这会创建与 A 团队中相同的一组用户,让我们运行上面的代码看看这是否是 True:

# fetch teams where user is already added
teams = [A, B] # user already there

# prepare list of tuples of sorted members id for each team
members_set = [(1, 2, 3), (1, 2, 4)]

# we know already in which team we want to add lets say it is `team_c` so it will become
team_c_members_set = (1, 2, 3) # tuple(sorted([3, 2] + [1]))

team_c_members_set in members_set # <-- True

一次性添加完整团队的场景

假设您要立即添加完整的团队 C,因此您已经知道您将在该团队中拥有哪些成员,在这种情况下过程几乎相似,但 team_c_members_set首先创建用于过滤团队:

users_to_add = [user_a, user_b, user_c]
team_c_members_set = tuple(sorted([u.id for u in users_to_add])
teams = Team.objects.filter(members__id__in=team_c_members_set).distinct()
will_clash = False
if teams:
# prepare list of tuples of sorted members id for each team
members_set = [tuple(team.members.values_list('id', flat=True).order_by('id')) for team in teams]
if team_c_members_set in members_set:
will_clash = True

if not will_clash:
# all good lets add the users in team
team_c.members.add(*users_to_add)

关于python - Django 对 ManyToManyField 中的成员集实现唯一约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46613062/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com