首页 > 解决方案 > Flask - SQLAlchemy - 将 nullable=False 列添加到包含数据的现有表中

问题描述

我正在尝试向nullable=False现有表添加一个新列。但它不会创建列,因为存在现有行且字段为Null.

这是一个经典的 22 :D。

这是我添加的模型列:

user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)

这是我得到的错误

sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) column "user_id" contains null values

我尝试添加, default=0到模型中属性的末尾,希望迁移只会将所有现有行的列值设置为0,但这没有任何效果。

我没有看到任何关于这种看似普遍现象的文档,所以我想我会问专家。我错过了什么?

标签: pythonflaskflask-sqlalchemyflask-migrate

解决方案


典型的错误消息如下所示。

sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) column "user_id" contains null values

一种解决方法是为现有记录设置外键 ID 0,然后将它们视为None在您的应用程序代码中。迁移中的升级将如下所示,其中您有两个表teamuser,并希望team_iduser记录中设置默认值 :

    team = op.create_table(
        "team",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("name", sa.Text(), nullable=False),
        sa.PrimaryKeyConstraint("id", name=op.f("pk_team")),
    )
    op.bulk_insert(
        team,
        [
            {"id": 0, "name": "Not Set"},
            {"id": 1, "name": "Team 1"},
            # ...
            {"id": N, "name": "Team N"},
        ],
    )


    op.add_column(
        "user",
        sa.Column("team_id", sa.Integer(), nullable=False, server_default="0"),
    )
    op.alter_column("user", "team_id", server_default=None)
    op.create_foreign_key(
        op.f("fk_team_id_user"),
        "user",
        "team",
        ["team_id"],
        ["id"],
        onupdate="CASCADE",
        ondelete="CASCADE",
    )

我可能已经让孩子和父母交换了,但这应该给你们一些尝试。


推荐阅读