[英]Alembic migration server default value is recognized as null when trying to update a column
我正在尝试进行迁移以根据has_bubble_in_countries
的列值更新has_bubble_v1
列的值。
我在upgrade()
之前创建了表:
subscription_old_table = sa.Table(
'Subscription',
sa.MetaData(),
sa.Column('id', sa.Unicode(255), primary_key=True, unique=True, nullable=False),
sa.Column('has_bubble_v1', sa.Boolean, nullable=False, default=False),
sa.Column('has_bubble_in_countries', MutableList.as_mutable(ARRAY(sa.Enum(Country))), nullable=False, default=[], server_default='{}')
)
然后upgrade()
方法如下所示:
def upgrade():
connection = op.get_bind()
for subscription in connection.execute(subscription_old_table.select()):
if subscription.has_bubble_v1:
connection.execute(
subscription_old_table.update().where(
subscription_old_table.c.id == subscription.id
).values(
has_bubble_in_countries=subscription.has_bubble_in_countries.append(Country.NL),
)
)
# Then drop the column after the data has been migrated
op.drop_column('Subscription', 'has_bubble_v1')
当我使用 pgadmin 的界面检查数据库时, has_bubble_in_countries
列数据库中的所有行都具有此值 {}。
当upgrade()
function 到达更新方法时,它会抛出此错误:
sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) null value in column "has_bubble_in_countries" of relation "Subscription" violates not-null constraint
DETAIL: Failing row contains (keydsakwlkad, null, 2027-08-14 00:00:00+00,groot abonnement, big, {nl}, null, null, 2022-08-08 08:45:52.875931+00, 3482992, {}, f, null, null, null, t, 2011-05-23 08:55:20.538451+00, 2022-08-08 09:10:15.577283+00, ***null***).
[SQL: UPDATE "Subscription" SET has_bubble_in_countries=%(has_bubble_in_countries)s::country[] WHERE "Subscription".id = %(id_1)s]
[parameters: {'has_bubble_in_countries': None, 'id_1': '1pwohLmjftAZdIaJ'}]
错误中的粗体值是为has_bubble_in_countries
列检索的值,即使它具有server_default='{}'
和nullable=False
也是如此。
是否有可能向 alembic 添加配置以在从数据库检索时识别服务器默认值? 或者如何解决?
我认为问题实际上是你传递的.append()
的结果是 None。 与通常返回更改后的列表的其他语言不同,append 会原地更改列表。 我不确定这对于此处的核心查询结果是否是个好主意,但它似乎有效。
with Session(engine) as session, session.begin():
for subscription in session.execute(subscription_old_table.select()):
if subscription.has_bubble_v1:
# Append here.
subscription.has_bubble_in_countries.append(Country.NL)
# Then set values:
session.execute(
subscription_old_table.update().where(
subscription_old_table.c.id == subscription.id
).values(has_bubble_in_countries=subscription.has_bubble_in_countries,
)
)
也许克隆列表然后像这样添加元素会更安全、更清晰:
has_bubble_in_countries=subscription.has_bubble_in_countries[:] + [Country.NL]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.