Alembic 的 server_default 和 Postgres

Clo*_*loC 5 python postgresql sqlalchemy alembic

我想使用 alembic 运行从 sqlalchemy 模型到另一个模型的迁移。初始模型如下所示:

from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy_utils import UUIDType

class Foo(db.Model):
    __tablename__ = 'foo'
    id = db.Column(UUIDType(binary=True), primary_key=True)
    foo_field = db.Column(JSONB)
Run Code Online (Sandbox Code Playgroud)

我想让它foo_field不可为空:

class Foo(db.Model):
    __tablename__ = 'foo'
    id = db.Column(UUIDType(binary=True), primary_key=True)
    foo_field = db.Column(JSONB, nullable=False)
Run Code Online (Sandbox Code Playgroud)

我想运行 alembic 脚本来更改列,但由于我现有的一些列为foo_field空,所以我想server_default在更改时应用默认值(空字典)

op.alter_column('foo',
         'foo_field',
         existing_type=postgresql.JSONB(astext_type=sa.Text()),
         nullable=False,
         server_default="{}")
Run Code Online (Sandbox Code Playgroud)

我尝试了不同的选项来传递给这个server_default,例如text("{}"),,,,。但它似乎被忽略了,我得到的只是 运行升级时的:lambda: {}{}text("SELECT '{}'")IntegrityError

sqlalchemy.exc.IntegrityError: (psycopg2.IntegrityError) column "foo_field" contains null values [SQL: 'ALTER TABLE foo ALTER COLUMN foo_field SET NOT NULL'] (Background on this error at: http://sqlalche.me/e/gkpj)
Run Code Online (Sandbox Code Playgroud)

表示空字典的字符串是否被视为非空?应该传递什么给这个server_default?在将字段设置为不可为空之前,我是否应该将代码分成多个步骤来填充默认值(不是首选选项,我有一堆想要应用此功能的列)?

我正在使用 postgres 10.5,我读到postgres 11 会更好地处理此类操作,我现在应该切换到它吗?

预先感谢您的帮助/建议

mos*_*evi 0

您可以使用 aRewriter并自行自动执行此操作。

覆盖ops.AlterColumnOp操作并返回两个操作,第一个是具有服务器默认值的更新列操作,第二个是原始操作op