使用SQLAlchemy的基本自动映射反射Postgres数据库中的IDENTITY列时出现"NULL identity key"错误。

8
我是一名有用的助手,可以为您翻译文本。

我有一个Postgres数据库,我正在尝试反映使用现在标准的“Identity”列作为主键。

这是我的表定义:

create table class_label (
    class_label_id integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    class_name varchar not null,
    default_color varchar,
    created_dttm timestamp default current_timestamp NOT NULL,
    created_by varchar DEFAULT USER NOT NULL,
    updated_dttm timestamp default current_timestamp NOT NULL,
    updated_by varchar DEFAULT user NOT NULL
);

这是我的代码:

from sqlalchemy import create_engine, MetaData, insert, Table, or_, and_, func
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import scoped_session, sessionmaker
import os

from sqlalchemy.schema import CreateColumn
from sqlalchemy.ext.compiler import compiles

@compiles(CreateColumn, 'postgresql')
def use_identity(element, compiler, **kw):
    text = compiler.visit_create_column(element, **kw)
    text = text.replace("SERIAL", "INT GENERATED BY DEFAULT AS IDENTITY")
    return text

usr = os.environ.get("POSTGRES_USR")
pwd = os.environ.get("POSTGRES_PWD")
host = os.environ.get("POSTGRES_HOST")

engine = create_engine('postgresql://' + usr + ':' + pwd + host, convert_unicode=True)
session = scoped_session(sessionmaker(bind=engine))
metadata = MetaData(bind=engine)

metadata.reflect(engine, only=['class_label'])
Base = automap_base(metadata=metadata)
Base.prepare()

Class_Label = Base.classes.class_label

session.add(Class_Label(class_name="Testing", default_color="red"))
session.commit()

当我运行代码时,出现以下错误:

sqlalchemy.orm.exc.FlushError: 实例 <class_label at 0x1091c4ba8> 的标识键为空。
如果这是自动生成的值,请检查数据库表是否允许生成新的主键值,并且映射的列对象已配置为期望这些生成的值。还要确保此 flush() 不会在不适当的时间内发生,例如在 load() 事件中。

根据https://docs.sqlalchemy.org/en/13/dialects/postgresql.html#postgresql-10-identity-columns,我了解到这在某种程度上是SQLAlchemy的缺点,但我想知道他们建议的解决方法是否适用于自动映射/反射的数据库,以及如何实现它。
我正在使用SQLAlchemy 1.3.16和Postgres 11。

4
目前正在GitHub上解决此问题。 - Gord Thompson
1个回答

2

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