I have a model Course
that have a ManyToMany relation with my CustomUser
model:
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('Email Address'), unique=True)
user_name = models.CharField(_('User Name'), max_length=150, unique=True)
# and a lot of other fields and stuff
class Course(models.Model):
enrolled_users = models.ManyToManyField(CustomUser, related_name="enrolls", blank=True)
previous_enrolled_users = models.ManyToManyField(CustomUser, related_name="previous_enrolls", blank=True)
course_name = models.CharField(_("Course Name"), max_length=200)
What I'm trying to implement is that whenever a user finishes a course (and so the user is removed from enrolled_users
), my application stores this user in previous_enrolled_users
, so I can know the users that were previously enrolled at that course.
I've implement a m2m_changed
signal listening like this:
def listen_m2mchange(sender, instance, model, pk_set, action, **kwargs):
if action == 'pre_remove':
# I'm trying to guess what to do
m2m_changed.connect(listen_m2mchange, sender=Course.enrolled_users.through)
With that, whenever I remove a user from a course, Django signals the m2m_changed
and I capture that signal. I know that instance
is the instance of the Course
class and that model
is the instance of that CustomUser
class I'm removing. What I could not guess is how, using the instance of Course
class, I can add the CustomUser
in the previous_enrolled_users. Any help will be very appreciated.
EDIT 01:
Reading a lot of the docs, I get that what I want is doing this everytime model
is removed from enrolled_users
:
instance.previous_enrolled_users.add(model)
But when I do it, I get an error:
TypeError: Field 'id' expected a number but got <class 'core.models.CustomUser'>.
Try this:
def listen_enrolled_users_m2mchange(sender, instance, model, pk_set, action, **kwargs):
if action == 'post_remove':
instance.previous_enrolled_users.add(*pk_set)
m2m_changed.connect(listen_enrolled_users_m2mchange, sender=Course.enrolled_users.through)
pk_set
here will be a set of primary keys that were involved in the changes of enrolled_users
field in Course
. That means when the action is post_remove
, all the removed CustomUser
primary keys will be passed in the pk_set
kwarg.
This then means that when the signal kicks in for the changes on enrolled_users
of Course
, we can check if the action is a remove. In that case, the same pk_set
we received that are removed from enrolled_users
can be directly added to previous_enrolled_users
.