我正在尝试在Postgresql表中插入一行,如下所示:
CREATE TABLE launch_ids(
id SERIAL PRIMARY KEY,
launch_time TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT
(now() at time zone 'utc')
);
我的类看起来像这样:
class LaunchId(Base):
"""Launch ID table for runs"""
__tablename__ = 'launch_ids'
id = Column(Integer, primary_key=True)
launch_time = Column(DateTime)
launch_time
应由数据库管理。我知道可以使用default=datetime.datetime.utcnow()
,但这使用客户端上的当前时间。我知道可以使用default=func.now()
,但这意味着如果数据库的默认定义发生变化,那么我需要在两个地方更改默认值。
这是我尝试在不指定值的情况下插入launch_ids
行时得到的:
l = LaunchId()
session.add(l)
session.commit()
IntegrityError: (psycopg2.IntegrityError) null value in column "launch_time" violates not-null constraint
DETAIL: Failing row contains (1, null).
[SQL: 'INSERT INTO launch_ids (launch_time) VALUES (%(launch_time)s) RETURNING launch_ids.id'] [parameters: {'launch_time': None}]
使用 FetchedValue
:
from sqlalchemy.schema import FetchedValue
class LaunchId(Base):
...
launch_time = Column(DateTime, FetchedValue())
指定列上的server_default
,如下所示:
class LaunchId(Base):
"""Launch ID table for runs"""
__tablename__ = 'launch_ids'
id = Column(Integer, primary_key=True)
launch_time = Column(DateTime, nullable=False
server_default=text("(now() at time zone 'utc')"))
然后,通过会话添加新launch_id将起作用。 server_default
的工作方式与default
不同,因为它是在服务器端生成的。官方 SQLAlchemy 文档:http://docs.sqlalchemy.org/en/latest/core/defaults.html#server-side-defaults
通过指定nullable=False
,此模型也成为您指定CREATE TABLE
的真实反映,因此可以通过Base.metadata.create_all
或使用alembic
生成。