2👍
✅
Hmm there is no direct way, but on top of my head this might work.
The only possibility of a set of members clash with another team members is only when the member which you are about to add exists in other teams, so first we need to fetch those teams in which user is already added:
# 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)
Dry Run:
Lets say you have following three teams:
Team A:
1: member
2: member
3: member
Team B:
1: member
2: member
4: member
Team C:
3: member
2: member
Now we want to add member id: 1
into team C
. Which should be avoided as that will create same set of users as in team A
, lets run the above code to see if that is 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
Scenario adding full team at once
Lets say you are adding full team C
at once, so you already know which members you will have in that team, in that case process is almost similar but team_c_members_set
is created first to be used in filtering teams
:
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)
Source:stackexchange.com