Django中外键关联模型实例属性更新的正确方式咨询
Django外键关联实例的更新逻辑解析
核心原因:Django ORM的内存缓存机制
Django ORM会把已查询到的模型实例存在内存中,同一个数据库记录,通过不同方式获取的内存实例是相互独立的,不会自动同步彼此的属性变化,也不会主动从数据库刷新数据,除非你手动触发。
三种写法的问题拆解
- 第一种写法(完全无效)
doc.company.status = new_value doc.save()
你只是修改了内存里doc关联的company实例属性,但调用doc.save()时,Django只会检查Document自身的字段变化——这里doc的company外键指向并未改变,所以不会把company的属性更新同步到数据库。数据库里的Company状态还是旧值,后续查询其他company实例自然拿不到新值。
- 第二种写法(数据库更新,但内存实例不同步)
setattr(company, 'status', new_value) company.save()
这段代码确实把company实例的修改同步到了数据库,但doc.company是之前查询出来的另一个内存缓存实例,Django不会自动更新这个缓存,所以它的status还是旧值。
- 第三种写法(有效,但内存缓存不会自动同步)
doc.company.status = new_value doc.company.save()
这次你修改了doc.company这个内存实例,并且调用了Company实例自身的save()方法,所以变化会同步到数据库。但之前已获取的company内存实例还是缓存的旧数据,要看到新值,你需要:
- 对
company实例调用company.refresh_from_db(),强制从数据库刷新属性 - 或者重新从数据库查询该Company记录(比如
Company.objects.get(id=company.id))
正确操作规范
- 修改外键关联对象的属性时,必须调用关联对象的
save()方法,而非主对象的save()——主对象的save仅处理自身字段的变化。 - 同一数据库记录的多个内存实例不会自动同步,要同步要么手动刷新实例,要么重新查询。
内容的提问来源于stack exchange,提问作者PBG
相关产品推荐
相关产品推荐

