使用PyMongo更新嵌套字典时遭遇ReferenceError问题求解
解决PyMongo/MongoEngine更新嵌套字典时的ReferenceError问题
错误原因
你遇到的ReferenceError: weakly-referenced object no longer exists,是因为直接从MongoEngine文档实例中取出的spare_2字典是对原文档对象的弱引用。当原文档实例被Python垃圾回收机制回收后,这个引用就失效了,后续尝试用它更新数据库自然会报错。
解决方案
方案1:深拷贝字段内容后修改
先把spare_2的内容深拷贝出来,脱离原文档实例的引用,修改后再更新:
from copy import deepcopy # 获取目标用户文档 user = User.objects.filter(username=current_user).first() if not user: # 处理用户不存在的情况 pass # 深拷贝spare_2,避免引用原文档对象 my_dict = deepcopy(user.spare_2) # 添加或更新quiz_id对应的内容 my_dict[quiz_id] = { 'question1': 9, 'question2': 9, 'question3': 9, 'question4': 9, 'question5': 9, 'question6': 9, 'question7': 9, 'question8': 9, 'question9': 9, 'question10': 9 } # 更新数据库 user.update(spare_2=my_dict)
方案2:使用原子更新(推荐)
直接用MongoEngine的原子更新操作,不需要取出整个字典,既避免引用问题,又能保证并发场景下的数据安全:
# 方式1:MongoEngine风格的嵌套更新 User.objects(username=current_user).update_one( set__spare_2__{quiz_id}={ 'question1': 9, 'question2': 9, 'question3': 9, 'question4': 9, 'question5': 9, 'question6': 9, 'question7': 9, 'question8': 9, 'question9': 9, 'question10': 9 } ) # 方式2:原生MongoDB操作符风格 User.objects(username=current_user).update_one( {"$set": {f"spare_2.{quiz_id}": { 'question1': 9, 'question2': 9, 'question3': 9, 'question4': 9, 'question5': 9, 'question6': 9, 'question7': 9, 'question8': 9, 'question9': 9, 'question10': 9 }}} )
注意:如果spare_2原本不存在,原子更新会自动创建该字段;如果quiz_id对应的键已存在,会直接覆盖原有值。
内容的提问来源于stack exchange,提问作者Aristotle
相关产品推荐
相关产品推荐

