Peewee框架update更新数据不生效问题排查 附实现代码
问题场景:更新数据表数据时Peewee更新逻辑始终未生效,对应实现代码如下:
async def save_edit_payment_type(callback_query: types.CallbackQuery, state: FSMContext): await callback_query.message.edit_reply_markup() user_data = await state.get_data() callback_data_payment = callback_query.data await state.update_data(callback_data_payment=callback_data_payment) if callback_data_payment == 'cash': await callback_query.message.answer('Выберите тип:', reply_markup=keyboards.additional_data) await WaiteEditOrder.waiting_purchase_or_sale_data.set() else: order = Order.get(id=user_data["index"]) order.update( payment_type=callback_data_payment, purchase_or_sale='', amount_to_be_paid=0, ) order.save() await state.finish()
常见原因及修复方案
核心用法错误:混淆类级update方法和实例更新逻辑
这是这段代码最直接的问题:Peewee的update()是模型类层面的批量更新方法,设计用来直接生成带WHERE条件的UPDATE语句、批量修改符合条件的行,不能在查询出来的单个模型实例上调用。在实例上调用update()不会修改实例本身的字段值,后续调用save()自然不会把传入的字段变更写入数据库。
两种正确的单条记录更新写法:- 实例属性赋值后调用save,适合已经查询出实例的场景:
order = Order.get(id=user_data["index"]) order.payment_type = callback_data_payment order.purchase_or_sale = '' order.amount_to_be_paid = 0 order.save()- 直接调用类级update方法,匹配条件后执行,不需要提前查询实例、也不需要额外调用save:
Order.update( payment_type=callback_data_payment, purchase_or_sale='', amount_to_be_paid=0, ).where(Order.id == user_data["index"]).execute()事务未提交导致更新回滚
如果数据库初始化时手动关闭了autocommit自动提交开关,且没有在更新操作后手动调用commit()提交事务,操作结束后事务会自动回滚,数据不会落库。非手动管理多步事务的场景下,不要随意关闭Peewee的默认自动提交配置。查询条件不匹配,未定位到目标记录
代码中通过Order.get(id=user_data["index"])查询待更新记录,如果user_data["index"]存在类型不匹配(比如存的是字符串格式ID,数据库主键是整数类型)、值不存在、值错误,要么查询抛出的DoesNotExist异常被上层逻辑吞掉,要么查到的不是目标记录,最终看不到预期的更新效果。可以在查询后打印实例ID和原始字段值,确认命中的是待修改的目标行。字段配置异常拦截更新
检查Order模型的字段定义:如果待更新的三个字段存在属性名拼写错误、column_name映射的数据库列名和实际不符、字段设置了只读约束、字段类型和传入值类型不匹配触发校验拦截,都会导致更新值无法正常写入。异步场景混用同步API导致操作未实际执行
这段代码是async异步函数,但调用的是原生Peewee的同步阻塞方法(get()/update()/save()都没有加await),如果异步运行时没有给同步IO操作分配独立线程池,会出现数据库连接阻塞、操作未实际提交的问题。如果是异步项目,建议使用peewee-async提供的异步API,所有数据库操作都加await调度,避免同步阻塞调用卡断逻辑。
内容的提问来源于stack exchange,提问作者Axel

