如何在 SQLAlchemy 中插入列的数据库默认值?



我正在尝试在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生成。

最新更新