字段默认时间戳设置为表创建时间而非行创建时间

9
使用SQLAlchemy、alembic和postgres时,当试图将列设置为行创建时间时,我最终得到的是一个默认为表本身创建时间而不是行创建时间的字段。
模型代码:
datetime = sa.Column(sa.DateTime, nullable=False, server_default=func.now())

Alembic将其翻译为:
sa.Column('datetime', sa.DateTime(), server_default='now()', nullable=False),

以及在Postgres中的列:

datetime  | timestamp without time zone | not null default '2013-06-24 11:28:14.930524'::timestamp without time zone

我该怎么做才能使默认时间为行创建时间?


你能否试一下server_default=func.now而不是server_default=func.now(),而不是提交一个正确的答案? - Doobeh
@Doobeh:我考虑过这个,因为它的目的是传递一个函数而不是一个值,所以这样做是有意义的,但似乎在SQLAlchemy中调用函数是正确的方法。尝试这样做会触发以下错误:sqlalchemy.exc.ArgumentError: 预期参数“arg”应该是类型之一 '<type 'basestring'>' 或 '<class 'sqlalchemy.sql.expression.ClauseElement'>' 或 '<class 'sqlalchemy.sql.expression.TextClause'>', 但得到了 '<class 'sqlalchemy.sql.expression._FunctionGenerator'>'。 - Artur Soler
1
有点冒险--我习惯于使用 default=datetime.now 来描述我的时间戳列。我找到了(并测试了)一种使用 server_default 的解决方案,我将其作为答案留下。 - Doobeh
1个回答

17

明白了——看起来你需要告诉 server_default 命令,如果你要发送一些需要在 DBMS 上执行的 SQL:

from sqlalchemy import text

class Test(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    created = db.Column(db.DateTime, server_default=text('now()'))

那将生成:

CREATE TABLE test (
    id SERIAL NOT NULL, 
    created TIMESTAMP WITHOUT TIME ZONE DEFAULT now(), 
    PRIMARY KEY (id)
)

谢谢,我之后会尝试。但这只适用于Postgres,对吗? - Artur Soler
你只需告诉它:“嘿,不要处理这一部分,只需将其添加到此列的SQL DDL中,不需要任何问题。” 如果您的DBMS使用OMG_RIGHT_NOW()而不是NOW(),那么您需要进行调整。 - Doobeh
最新的SQLAlchemy文档对此更加清晰明了;例如,请参阅关于server_default的1.13文档 - brotskydotcom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接