Django OneToOneField调用save()后关联丢失返回None问题求解
问题根本原因
这个现象是Django ORM 关联属性的缓存逻辑和外键底层字段的更新规则导致的,和是否用中间变量没有直接关系,核心差异是外键字段category_id的赋值时机。
第一种写法的执行逻辑拆解
- 执行
post.category = Category(name='My Category')时,你赋值的是还未保存、没有主键的Category实例,此时Django只会把这个实例暂存在post的关联属性缓存中,因为关联对象没有主键,所以不会同步更新post底层的外键字段category_id,category_id此时仍然为None。 - 执行
post.category.save()时,只会给Category实例生成主键、保存到数据库,不会主动回写更新post的category_id字段。此时你访问post.category能拿到带主键的实例,读的是ORM缓存的值,底层category_id依旧是空。 - 执行
post.save()时,Django会把post实例当前的所有字段值写入数据库,category_id是空就会存为空值。保存完成后ORM会自动清空关联属性的缓存,你再次访问post.category时,ORM会根据category_id的值去加载关联对象,自然就返回None。
第二种写法正常的原因
你先单独保存Category实例拿到主键后,再把带主键的实例赋值给post.category,此时Django会自动把Category的主键同步赋值给post.category_id,保存post的时候外键字段有有效值,自然不会丢失关联。
如果不想额外声明中间变量,也可以在保存完分类后手动同步外键值,写法如下:
post = Post(title='My Title') post.category = Category(name='My Category') post.category.save() # 手动同步外键值 post.category_id = post.category.pk post.save() # 此时post.category就可以正常获取
内容的提问来源于stack exchange,提问作者achedeuzot
相关产品推荐
相关产品推荐

