sqlalchemy onupdate противоречивое поведение для Query.update () - PullRequest
0 голосов
/ 22 декабря 2018

Я реализую спокойный POST API с Flask, использую 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, который остается нулевым;Я ожидаю, что он будет обновлен с указанием текущей даты и времени.

Если я удаляю поле time_updated из ввода перед вызовом Query.update (),

input_instance_dict.pop('time_updated', None)

, тогда нулевое значение вСтолбец time_updated будет обновляться с указанием текущей даты, НО ... при последующих обновлениях значение этого столбца остается прежним.

Я сомневаюсь, что даже при удалении поля time_updated из входных данныхonupdate вступает в силу только при первом обновлении, но не после.Зачем?Спасибо.

--- Обновление 12/23 10:56 по Гринвичу + 8

Дополнительное наблюдение, я только что повторно запустил то же обновление, что и прошлой ночью, *Столбец 1027 * обновляется для первой попытки, но не для второй.Это означает, что после самого первого обновления onupdate включается и выключается для следующих обновлений.Я не могу понять шаблон, когда он будет работать, а когда нет.

1 Ответ

0 голосов
/ 10 января 2019

Аналогичная проблема наблюдается и для другого поля отметки времени, которое должно быть заполнено 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())

I 'Я не уверен, почему разница в поведении, есть много учебных пособий, которые используют функцию datetime в качестве аргумента, мне интересно, если эти программы имеют ту же проблему.

...