我正在使用 Flask 实现一个 restful POST API,使用 sqlalchemy 更新 PostgreSQL 中的资源,例如 MyResource:
class MyResource(db.Model):
__tablename__ = 'my_resource'
res_id = Column(Integer, primary_key=True)
<other columns>
time_updated = Column(TIMESTAMP(timezone=True), onupdate=datetime.now(timezone.utc))
有一个 MyResource
实例来自 API 的请求负载,我们称它为 input_instance
。以下是我更新资源的方法:
input_instance_dict = input_instance.__dict__
input_instance_dict.pop('_sa_instance_state', None) # this extra meta field will cause error in update().
update_count = MyResource.query.filter(MyResource.res_id == input_instance.res_id).update(input_instance_dict)
db.session.commit()
在上面,除了 time_updated
之外的列都被更新了,它仍然是空的;我希望它会更新为当前日期时间。
如果我在调用 Query.update() 之前从输入中删除 time_updated
字段,
input_instance_dict.pop('time_updated', None)
然后 time_updated
列中的空值将更新为当前日期时间,但是......在后续更新中,该列的值保持相同的旧值。
我的疑问是,即使从输入字典中删除了 time_updated
字段,onupdate
也只在第一次更新时生效,之后不会。为什么?谢谢。
--- 更新 12/23 10:56am GMT+8
额外的观察,我只是重新触发了与昨晚两次相同的更新,time_updated
列在第一次重试时更新,但在第二次重试时没有更新。这意味着,在第一次更新之后,onupdate
会在后续更新时开启和关闭。我无法弄清楚这种模式,什么时候可以,什么时候不能。
最佳答案
对于用 default
填充的其他时间戳字段也观察到类似的问题,比如说...昨天插入了一条记录,但今天插入的所有记录最终都具有相同的 time_created
值为昨天的值。
time_created = Column(TIMESTAMP(timezone=True), nullable=False, default=datetime.now(timezone.utc))
更改参数后(对于 default
和 onupdate
),将 python datetime
函数替换为 sqlalchemy.func.now( )
解决了奇怪的行为。
time_created = Column(TIMESTAMP(timezone=True), nullable=False, default=func.now())
time_updated = Column(TIMESTAMP(timezone=True), onupdate=func.now())
我不确定为什么行为不同,有很多教程使用 datetime 函数作为参数,我想知道那些程序是否有同样的问题。
关于python - Query.update() 的 sqlalchemy onupdate 不一致行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53894803/