Reputation: 1949
I'm implementing a restful POST API with Flask, using sqlalchemy to update resource in PostgreSQL, say 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))
There's a MyResource
instance derived from API's request payload, let's call it input_instance
. Below is my approach for updating the resource:
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()
With above, columns are updated except time_updated
, which remains null; I expect it to be updated with current date time.
If I remove the time_updated
field from input prior to calling Query.update(),
input_instance_dict.pop('time_updated', None)
then the null value in time_updated
column will be updated with current date time, BUT... on subsequent updates, this column's value remains the same old value.
My doubt is that, even with time_updated
field removed from input dict, onupdate
only takes effect for first update but not afterwards. Why? Thanks.
--- Update 12/23 10:56am GMT+8
Additional observation, I just re-triggered the same update as last night's twice, time_updated
column is getting updated for first retry but not the second ones. Which means, After the very first update, onupdate
takes effect on and off for following updates. I can't figure out the pattern, when it'll work and when it won't.
Upvotes: 1
Views: 1366
Reputation: 1949
Similar problem is also observed for the other timestamp field to be populated with default
, say... a record was inserted yesterday, but all records inserted today end up having the same time_created
value as yesterday's value.
time_created = Column(TIMESTAMP(timezone=True), nullable=False, default=datetime.now(timezone.utc))
After changing the argument (for default
and onupdate
), replacing the python datetime
function with sqlalchemy.func.now()
resolves the weird behaviour.
time_created = Column(TIMESTAMP(timezone=True), nullable=False, default=func.now())
time_updated = Column(TIMESTAMP(timezone=True), onupdate=func.now())
I'm not sure why the behaviour difference, there are many tutorials that using datetime function as argument, I wonder if those programs having the same problem.
Upvotes: 1