SQLAlchemy 和 PostgreSQL 更新后时间戳相同

问题描述 投票:0回答:1

在下面的代码中,在 5 秒睡眠后,我希望

date_updated
的第二部分发生变化,但只有毫秒部分发生变化。如果我使用
database_url = 'sqlite:///:memory:'
它会按预期工作。为什么?

class Base(MappedAsDataclass, DeclarativeBase):
    pass


class Test(Base):
    __tablename__ = 'test'

    test_id: Mapped[int] = mapped_column(primary_key=True, init=False)
    name: Mapped[str]
    date_created: Mapped[datetime] = mapped_column(
        TIMESTAMP(timezone=True),
        insert_default=func.now(),
        init=False
    )
    date_updated: Mapped[datetime] = mapped_column(
        TIMESTAMP(timezone=True),
        nullable=True,
        insert_default=None,
        onupdate=func.now(),
        init=False
    )


database_url: URL = URL.create(
    drivername='postgresql+psycopg',
    username='my_username',
    password='my_password',
    host='localhost',
    port=5432,
    database='my_db'
)
engine = create_engine(database_url, echo=True)
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)

with Session(engine) as session:
    test = Test(name='foo')
    session.add(test)
    session.commit()

    print(test)
    
    time.sleep(5)

    test.name = 'bar'    
    session.commit()

    print(test.date_created.time()) # prints: 08:07:45.413737
    print(test.date_updated.time()) # prints: 08:07:45.426483
python postgresql sqlalchemy
1个回答
0
投票

PostgreSQL 的 now() 函数返回当前事务的开始时间。在问题的代码中,第二个事务是由

print
语句触发的,因为必须打开一个新事务来检索前一个
commit
过期的值。因此观察到的时间戳的差异只有几毫秒。

为了获得所需的行为,这些方法中的任何一种都应该有效:

  • 不要在提交时过期:
    with orm.Session(engine, expire_on_commit=False) as session:
    
  • 删除
    print()
    通话
  • 拨打
    session.comiit()
    后再次拨打
    print()
© www.soinside.com 2019 - 2024. All rights reserved.