SQLAlchemy 默认日期时间

新手上路,请多包涵

这是我的声明模型:

 import datetime
from sqlalchemy import Column, Integer, DateTime
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Test(Base):
    __tablename__ = 'test'

    id = Column(Integer, primary_key=True)
    created_date = DateTime(default=datetime.datetime.utcnow)

但是,当我尝试导入此模块时,出现此错误:

 Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "orm/models2.py", line 37, in <module>
    class Test(Base):
  File "orm/models2.py", line 41, in Test
    created_date = sqlalchemy.DateTime(default=datetime.datetime.utcnow)
TypeError: __init__() got an unexpected keyword argument 'default'

如果我使用 Integer 类型,我可以设置一个默认值。这是怎么回事?

原文由 Brandon O‘Rourke 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.8k
2 个回答

DateTime 没有默认键作为输入。默认键应该是 Column 函数的输入。试试这个:

 import datetime
from sqlalchemy import Column, Integer, DateTime
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Test(Base):
    __tablename__ = 'test'

    id = Column(Integer, primary_key=True)
    created_date = Column(DateTime, default=datetime.datetime.utcnow)

原文由 PearsonArtPhoto 发布,翻译遵循 CC BY-SA 3.0 许可协议

在您的数据库中计算时间戳,而不是您的客户端

为了理智,您可能希望所有 datetimes 都由您的数据库服务器计算,而不是应用程序服务器。在应用程序中计算时间戳可能会导致问题,因为网络延迟是可变的,客户端体验略有不同的时钟漂移,并且不同的编程语言偶尔会略微不同地计算时间。

SQLAlchemy 允许您通过传递 func.now()func.current_timestamp() (它们是彼此的别名)告诉数据库自己计算时间戳。

使用 SQLALchemy 的 server_default

此外,对于您已经告诉数据库计算值的默认值,通常最好使用 server_default 而不是 default 。这告诉 SQLAlchemy 传递默认值作为 CREATE TABLE 语句的一部分。

例如,如果您针对该表编写一个临时脚本,使用 server_default 意味着您无需担心手动向脚本添加时间戳调用——数据库会自动设置它。

理解 SQLAlchemy 的 onupdate / server_onupdate

SQLAlchemy 还支持 onupdate 以便在更新行时插入新的时间戳。同样,最好告诉数据库自己计算时间戳:

 from sqlalchemy.sql import func

time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), onupdate=func.now())

有一个 server_onupdate 参数,但与 server_default 不同,它实际上没有在服务器端设置任何内容。它只是告诉 SQLAlchemy,当发生更新时,您的数据库将更改该列(也许您 在该列上创建了一个触发器),因此 SQLAlchemy 将请求返回值,以便它可以更新相应的对象。

另一个潜在问题:

您可能会惊讶地发现,如果您在单个事务中进行了一系列更改,它们都具有相同的时间戳。那是因为 SQL 标准指定 CURRENT_TIMESTAMP 返回基于事务开始的值。

PostgreSQL 提供了非 SQL 标准 statement_timestamp()clock_timestamp() 它们 在事务中发生变化。此处的文档: https ://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT

UTC 时间戳

如果您想使用 UTC 时间戳, SQLAlchemy 文档 中提供了 func.utcnow() 的存根实现。不过,您需要自己提供适当的特定于驱动程序的功能。

原文由 Jeff Widman 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏