Django中ManyToManyField.add方法不生效问题排查求助
问题
我定义了名为TopicRoom的模型,其中creator字段是指向User模型的外键,members字段是与User模型关联的多对多字段。
我编写了如下post_save信号接收器代码:
@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 shell查询时,成员列表同样为空:
>>> TopicRoom.objects.get(id=24).members.all() <QuerySet []>
解决方案
问题出在Django的事务机制上:当post_save信号触发时,创建TopicRoom的事务还未提交,此时添加多对多关联的操作仅在内存中的实例里生效,并没有真正持久化到数据库,所以控制台打印能看到结果,但实际数据库中没有记录。
解决的关键是把添加成员的逻辑延迟到事务提交后执行,使用transaction.on_commit即可:
修改后的信号代码:
from django.db import transaction from django.db.models.signals import post_save from django.dispatch import receiver from .models import TopicRoom @receiver(post_save, sender=TopicRoom) def add_topic_room_creator_as_a_member(instance, created, **kwargs): if created: def add_creator_to_members(): instance.members.add(instance.creator) # 等待主事务提交后再执行关联操作 transaction.on_commit(add_creator_to_members)
修改后重新测试:在admin创建实例后,不管是刷新admin页面还是通过shell查询,都能看到members字段包含创建者了。
内容的提问来源于stack exchange,提问作者Rashaad
相关产品推荐
相关产品推荐

