我正在用Flask实现一个宁静的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
也仅对第一次更新有效,而对之后的更新无效。为什么?谢谢。
--- GMT + 8更新12/23 10:56 am
其他观察,我只是重新触发了与昨晚两次相同的更新,time_updated
列正在为第一次重试而更新,而没有为第二次重试。这意味着,在第一次更新后,onupdate
会在以后的更新中开启和关闭。我无法弄清楚这种模式,什么时候可以用,什么时候不可以用。
答案 0 :(得分:0)
对于另一个要填充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函数作为参数,我想知道这些程序是否存在相同的问题。