Django model ManyToManyField.add is not working

I have a model named TopicRoom and it has a field called creator which is a foreign key to the user model. And a many to many field called members which is a many to many rel to the user model


@receiver(post_save, sender=models.TopicRoom)
def add_topic_room_creator_as_a_member(instance, created, **kwargs):
    if created:
        print("added creator", instance.creator, instance)
        instance.members.add(instance.creator)
        print(instance.members.all())

When I create a new instance in the admin panel it prints this

added creator bob@gmail.com TopicRoom object (24)
<QuerySet [<User: bob@gmail.com>]>

but when I view the model in the admin panel it shows that there are no members. And when I retrieve the model from the django manage.py shell, that also shows that there are no members for that object instance

>>> TopicRoom.objects.get(id=24).members.all()
<QuerySet []>

This is a very common issue with post_save Django signals depending on how you are handling data and data structures.

But the good thing is this can be solved easily using transaction.on_commit() method. Ref: Performing actions after commit

Update your add_topic_room_creator_as_a_member function like this:

from django.db import transaction
@receiver(post_save, sender=models.TopicRoom)
def add_topic_room_creator_as_a_member(sender, instance, created, **kwargs):
    if created:
        def add_member():
            instance.members.add(instance.creator)
            print(instance.members.all())

        transaction.on_commit(add_member)

transaction.on_commit makes sure your function runs after the successful completion of the current transaction.

Try using:

instance.save()

after

print(instance.members.all())

Did you set relative names for both fields? because Django creates a default relative name "model_set. In your case, you are using the User model two times.

Back to Top