主要观点:在将应用从 Python 升级到 Django 5 时,在 QA 环境中遇到一个神秘的IntegrityError
异常,即对象无法保存因为主键已存在于数据库中,经过一系列排查和实验,最终发现是 Django 模型定义和实际数据库架构因历史原因漂移,主键类型不一致导致,且 Django 5.0 中关于过滤溢出整数值的规定使得问题暴露。
关键信息:
- 在开发环境工作正常,部署到 QA 环境后出现问题,错误信息为
IntegrityError
。 - 代码中未手动分配
id
,只是查询并更新现有记录,但 Django 却尝试插入新行。 - 多人从不同角度排查,发现只有部分记录有问题,且仅在 Django 中出现,在 Postgres 中正常。
- 查看 Django 使用的查询集发现为空,导致认为记录是新的应插入而不是更新。
- 发现 Django 模型定义和实际数据库架构中主键类型不一致,有问题的记录
id
在int
范围外。 - 回顾 Django 5.0 发行说明,其中提到过滤溢出整数值的规定与当前问题相关。
重要细节: - 代码示例为
object = models.Model.filter(property1=value).get()\nobject.property2 = method_result()\nobject.save()
。 - 尝试各种方法来缩小问题范围,如简化代码、强制更新等。
- 同事尝试获取不同
id
的记录,发现只有部分id
在int
范围外的记录有问题。 - Django 5.0 之前版本允许“不可能”的比较,而 5.0 版本强制内部正确性拒绝了该比较。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。