Reputation: 9610
I was kind of trying to see similar questions (Django accessing ManyToMany fields from post_save signal), but still don't see how to get the updated related objects list.
E.g. I have following models
class User(models.Model):
username = models.CharField
class Blog(models.Model):
user = models.ManyToManyField('User')
Now I am adding a user to a given blog, via django admin.
So I expect that the signal below, will print all new users (which I have just added)... but... I am getting the old list all the time :(
@receiver(m2m_changed, sender=Blog.users.through)
def blog_users_change(sender, instance, **kwargs):
print instance.users.all()
The last line gives old list of users instance.users.all()
. E.g. users added here are not reflected.
Upvotes: 2
Views: 3091
Reputation: 31404
m2m_changed
signals are fired at several stages in the save/update process, and there is an action
argument supplied to the signal handler that tells you what stage it is in. From the documentation:
action
A string indicating the type of update that is done on the relation. This can be one of the following:
"pre_add" Sent before one or more objects are added to the relation.
"post_add" Sent after one or more objects are added to the relation.
"pre_remove" Sent before one or more objects are removed from the relation.
"post_remove" Sent after one or more objects are removed from the relation.
"pre_clear" Sent before the relation is cleared.
"post_clear" Sent after the relation is cleared.
If you catch the pre_remove
action then you will get all the objects before some have been removed from the relationship. That is why you are seeing an apparently unchanged list of users.
Your code needs to check the action
before deciding what to do. For example:
@receiver(m2m_changed, sender=Blog.users.through)
def blog_users_change(sender, instance, action, **kwargs):
if action == 'pre_remove':
# This will give you the users BEFORE any removals have happened
print instance.users.all()
elif action == 'post_remove':
# This will give you the users AFTER any removals have happened
print instance.users.all()
Upvotes: 5