I want to add / remove members from a Team model. Members are specified as a ManyToManyField. I use django-rules to specify permissions, so team owners should be able to add/remove members.
# models.py
from django.db import models
from rules.contrib.models import RulesModel
from django.conf import settings
class Team(RulesModel):
name = models.CharField(max_length=80)
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
help_text="Owner can view, change or delete this team.",
related_name="team_owner",
)
members = models.ManyToManyField(
settings.AUTH_USER_MODEL, blank=True, related_name="team_members"
)
The permissions are specified as following:
import rules
@rules.predicate
def is_team_owner(user, obj):
return obj.owner == user
rules.add_perm("teamapp.change_team", is_team_owner)
I've specified some generic views (CreateView, DetailView, UpdateView and DeleteView) to manage the Team. Now I want two separate views to add and remove members on the same.
# views.py
from django.views.generic import (
CreateView,
DetailView,
UpdateView,
ListView,
DeleteView,
)
from rules.contrib.views import PermissionRequiredMixin
from django.contrib.auth import get_user_model
from .models import Team
class TeamMemberAddView(PermissionRequiredMixin, UpdateView):
model = Team
permission_required = "teamapp.change_team"
raise_exception = True
fields = ["members"]
def form_valid(self, form):
user = get_user_model()
new_member = user.objects.get(pk=1)
self.object.members.add(new_member)
return super(TeamMemberAddView, self).form_valid(form)
Which generic view can I use to add / remove members? Which approach is recommended here? I wanted 1 dedicated view to select an existing User to be added, and some links on the list view to delete members. My approach fails, because it does not add members, it only updates to the last User selected. So the ManyToMany table only contains one record.
TL;DR: replace the last line of
form_validbyreturn HttpResponseRedirect(self.get_success_url())It's important to understand how form_valid of UpdateView works. I recommend to visualize the methods on ccbv.co.uk.
From
ModelFormMixin:If the form is valid, save the associated model.
It means that the object will be saved with the data submitted by the form. UpdateView will restrict the changes to the fields variable:
From
FormMixin:If the form is valid, redirect to the supplied URL.
For your concrete case (add a many-to-many relationship), you need to bypass the model saving from
ModelFormMixinby simply returning the supplied URL after adding the relationship (last line changed):Side note: your form seems to provide the member object you want to add, so you could use this instead of including it in the url. Try: