使用Tortoise ORM更新数据库记录无效,求排查与优化方案
问题描述
我尝试使用Tortoise ORM更新数据库记录,编写了如下CRUD代码:
async def update( self, id: Any, obj_in: UpdateSchemaType ) -> ModelType: db_obj: ModelType = await self.model.filter(id = id).first() data_update = jsonable_encoder(obj_in, exclude_unset=True) db_obj_update = await db_obj.update_from_dict(data_update) return db_obj_update
其中UpdateSchemaType是Pydantic模型,ModelType是Tortoise模型。我在FastAPI中使用PUT路径操作:
@users_router.put( '/{user_id}', name = "Update user" ) async def update_user(user_id: int, user_update: schemas.UserUpdate): 'Update user' return await crud.user.update(user_id, user_update)
运行API后未出现报错,但数据库记录并未更新!请问我哪里出错了?该如何实现高效有效的更新?
问题原因与解决方案
Tortoise ORM的update_from_dict()方法仅会修改内存中的模型对象,不会自动将变更提交到数据库,这是导致数据没更新的核心原因。另外还需要确认两个关键点:是否正确查询到了目标对象、exclude_unset=True是否符合你的更新需求(它只会包含Pydantic模型中被显式设置的字段,忽略默认值字段)。
方案一:修改现有代码,手动提交变更
在调用update_from_dict()后,调用save()方法将变更写入数据库,同时增加对象存在性检查避免报错:
async def update( self, id: Any, obj_in: UpdateSchemaType ) -> ModelType: db_obj: ModelType = await self.model.filter(id = id).first() # 检查是否查询到目标对象 if not db_obj: raise HTTPException(status_code=404, detail="目标对象不存在") data_update = jsonable_encoder(obj_in, exclude_unset=True) await db_obj.update_from_dict(data_update) # 关键步骤:提交变更到数据库 await db_obj.save() return db_obj
方案二:更高效的批量更新(无需先查询对象)
如果不需要返回更新后的完整对象,或者想减少数据库查询次数,可以直接使用Tortoise的update()方法批量更新,这种方式性能更优:
async def update( self, id: Any, obj_in: UpdateSchemaType ) -> ModelType: data_update = jsonable_encoder(obj_in, exclude_unset=True) # 直接过滤并更新,返回受影响的行数 updated_count = await self.model.filter(id=id).update(**data_update) if updated_count == 0: raise HTTPException(status_code=404, detail="目标对象不存在") # 若需要返回更新后的对象,再执行一次查询 return await self.model.filter(id=id).first()
这种方式仅需1-2次数据库操作(取决于是否需要返回对象),比先查询再更新的模式更高效,尤其适合批量更新场景。
内容的提问来源于stack exchange,提问作者Diegol
相关产品推荐
相关产品推荐

