PostgreSQL配合Peewee ORM更新行时如何自动更新时间戳字段?
问题原因
你遇到的问题核心原因有两点:
- PostgreSQL表中
added_date字段设置的DEFAULT NOW()仅在插入新行时生效,执行UPDATE操作时不会自动触发默认值更新 - 你的更新逻辑中没有主动为
added_date字段赋值,因此该字段不会随更新操作变化
另外注意你的模型字段定义存在不匹配问题:建表时store_id是INTEGER类型,但模型里定义成了TextField,建议修改为IntegerField避免后续隐性类型转换的隐患。
解决方法
方案1:更新语句手动赋值(最简单,无额外配置)
直接在update方法中加入added_date的赋值逻辑即可,推荐使用Peewee内置的fn.NOW()调用数据库当前时间,避免应用与数据库时间不一致的问题:
- 先导入依赖:
from peewee import fn
- 修改更新代码:
cls.update(visible=False, added_date=fn.NOW()).where((cls.store_id == Stores.store_id) & (cls.url == pageData.url)).execute()
方案2:数据库触发器(全局生效,无需修改业务代码)
如果你希望所有对products表的更新操作都自动刷新added_date,可以直接在PostgreSQL中创建触发器,不管使用什么工具操作数据库都会生效:
- 创建触发函数:
CREATE OR REPLACE FUNCTION update_products_added_date() RETURNS TRIGGER AS $$ BEGIN NEW.added_date = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql;
- 绑定触发器到表:
CREATE TRIGGER trigger_products_update BEFORE UPDATE ON products FOR EACH ROW EXECUTE FUNCTION update_products_added_date();
配置完成后原有业务代码不需要做任何修改。
方案3:模型层面统一配置(无需修改数据库,业务代码无感知)
如果你不想修改数据库,也不想每次写更新都手动加字段,可以重写模型的update方法自动注入时间更新逻辑:
class Products(Model): id = IntegerField(column_name='id') # 修正字段类型和建表定义一致 store_id = IntegerField(column_name='store_id') url = TextField(column_name='url') visible = BooleanField(column_name='visible') added_date = TimestampField(column_name='added_date') class Meta: database = postgres_pool db_table = "products" @classmethod def update(cls, *args, **kwargs): # 自动注入added_date更新逻辑 kwargs['added_date'] = fn.NOW() return super().update(*args, **kwargs) # 原有on_exists方法不需要做任何修改
重写后你原来的更新代码不需要调整,调用update时会自动带上added_date的赋值逻辑。
内容的提问来源于stack exchange,提问作者PythonNewbie
相关产品推荐
相关产品推荐

