Django модель ManyToManyField.add не работает

У меня есть модель с именем TopicRoom, в ней есть поле creator, которое является внешним ключом к модели пользователя. И поле "многие ко многим" под названием members, которое является "многие ко многим" по отношению к пользовательской модели


@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())

Когда я создаю новый экземпляр в панели администратора, он выводит следующее

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

но когда я просматриваю модель в панели администратора, она показывает, что в ней нет членов. И когда я получаю модель из оболочки django manage.py, это также показывает, что для данного экземпляра объекта нет членов

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

Это очень распространенная проблема с сигналами post_save Django в зависимости от того, как вы работаете с данными и структурами данных.

Но хорошо то, что это можно легко решить с помощью метода transaction.on_commit(). Ref: Выполнение действий после фиксации

Обновите свою функцию add_topic_room_creator_as_a_member следующим образом:

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 обеспечивает выполнение вашей функции после успешного завершения текущей транзакции.

Попробуйте использовать:

instance.save()

после

print(instance.members.all())

Вы задали относительные имена для обоих полей? Потому что Django создает относительное имя по умолчанию "model_set". В вашем случае вы используете модель User два раза.

Вернуться на верх