Django中使用相同ID的模型实例更新未知差异字段是否合理?
结论:这种更新方式不合理,属于非常不推荐的危险写法
存在的问题如下:
- 全字段覆盖风险:你新创建的
Person实例仅手动赋值了name、surename、tel三个字段,若数据库中该条目还有其他字段(比如age、address等),调用save()时会直接将未赋值的字段覆盖为模型定义的默认值(或Null),直接造成数据丢失。哪怕当前模型只有这三个字段,后续新增字段后旧代码也会立即触发数据异常。 - 代码存在低级拼写错误:示例中数据库存储的姓氏字段是
surename,查询条件里写的是surname,实际运行会直接抛出字段不存在的异常。 - 额外性能开销:该写法先执行了一次数据库查询获取旧实例,再执行全字段更新,一共两次数据库交互;而直接调用
update方法仅需一次数据库操作,同时update仅更新指定字段,写入开销远低于全字段覆盖。 - 存在并发更新丢失风险:从查询旧实例到保存新实例的间隔中,如果有其他请求修改了该条数据,当前写法会直接覆盖其他请求的修改,引发数据不一致。
- 查询逻辑隐患:示例中用
name和surename作为查询条件,业务字段可能存在重复,一旦出现重名数据会触发MultipleObjectsReturned报错,或查错数据引发误更新。
正确的更新写法参考:
场景1:需要先获取实例做其他逻辑判断
# 优先用主键作为查询条件,保证唯一 old_p = Person.objects.get(id=4) old_p.tel = '0000000111' # 指定更新字段,避免全字段覆盖 old_p.save(update_fields=['tel'])
场景2:仅需要更新字段无需读取数据
# 一次数据库操作,性能最高 Person.objects.filter(id=4).update(tel='0000000111')
内容的提问来源于stack exchange,提问作者Charalamm
相关产品推荐
相关产品推荐

