Django使用.update()更新外键字段打印正常但数据库无变更问题
问题根因
你遇到的打印结果符合预期但数据库无变更的核心原因是update操作所在的事务最终被回滚,没有持久化到数据库,另外代码本身也存在逻辑冗余、命名不规范的问题:
- 事务未正常提交:Django 中如果开启了请求级事务(
ATOMIC_REQUESTS = True)或者手动给视图加了@transaction.atomic装饰器,只要视图执行过程中抛出异常,整个请求内的数据库操作都会被回滚。你在同一个事务会话内执行get查询可以读到未提交的变更,但事务回滚后数据不会写入数据库。如果你的代码是在Django的TestCase测试用例中运行,默认每个用例执行完都会自动回滚事务,也会出现这个现象。 - 判断条件逻辑错误:你的
if判断中proveedor == ""完全无效,遍历得到的proveedor是EstandarProducto模型实例,永远不可能等于空字符串,这段冗余逻辑虽然不影响执行,但有潜在的逻辑风险。 - 变量命名不规范:你将
EstandarProducto查询集的遍历变量命名为proveedor,极易和外键字段proveedor混淆,增加代码维护难度。 - 低级错误排查:可以确认你查看的数据库和Django配置文件中连接的数据库是否为同一个,避免出现连错库的问题。
解决步骤
1. 事务问题修复
- 检查视图执行过程中是否抛出未捕获的异常,异常会触发事务回滚;
- 如果是在测试代码中运行,将
TestCase替换为TransactionTestCase即可看到数据库中的实际写入结果,或者在测试代码中手动调用transaction.commit()提交事务。
2. 修正并优化代码
你目前的循环单条更新写法性能极低,完全可以用Django查询集的批量更新能力替代,不需要遍历:
# 直接批量过滤proveedor_id为空的记录,一次性更新 EstandarProducto.objects.filter( recinto=id_recinto, proveedor_id__isnull=True ).update(proveedor_id=1)
如果需要保留循环逻辑,修正后代码如下:
estandares = EstandarProducto.objects.select_related('recinto','producto','proveedor').prefetch_related(Prefetch('carreras')).filter(recinto=id_recinto) # 修改变量名避免混淆 for estandar in estandares: # 修正判断条件,移除无效的空字符串判断 if estandar.proveedor_id is None: EstandarProducto.objects.filter(id=estandar.id).update(proveedor_id=1) x=EstandarProducto.objects.get(id=estandar.id) print("ID proveedor : ", x.proveedor.id )
内容的提问来源于stack exchange,提问作者Nuevakenia
相关产品推荐
相关产品推荐

