SQLAlchemy:跨模式的外键

SQLAlchemy: ForeignKey across schemas

在我的 postgres 服务器中,我们有一个数据库 database,其中包含 2 个模式:publicapipublic 有几个 table,我需要在 api 中创建一个 table,并在 public 中创建一个 table 的外键,称为 model。 所以它是:

-Schemas
--public
---tables
----models
--api
---tables

使用 SQLAlchemy 我有以下 class:

from sqlalchemy import create_engine, MetaData, Table, Column

class __PostgresService:
  def __init__(self):
    self.__client = create_engine("postgresql://postgres@localhost:5432/database")
    metadata = MetaData(self.__client, schema="public")
    self.__table = Table("training", metadata,
                         Column("id", String, primary_key=True, nullable=False),
                         Column("model_id", ForeignKey("model.id"), nullable=False),
                         schema="api")
    metadata.create_all()

postgres_service = __PostgresService()

但是在启动时我收到以下错误:

sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'training.model_id' could not find table 'public.model' with which to generate a foreign key to target column 'id'

看起来它确实在寻找正确的东西但找不到?我很困惑为什么会发生这种情况,特别是因为错误指的是找不到“public”,它是由 postgres 默认创建的,而不是“api”我在 pgAdmin 中创建了自己。 我是否缺少一些关键配置?

您收到的错误意味着您正在尝试创建一个引用 SQLAlchemy 不知道的 table 的外键。您可以通过创建与描述引用的 table 的相同 MetaData 关联的 Table 来告知 sqlalchemy。您也可以使用 sqlalchemy 的 reflection capabilities 来执行此操作。例如:

from sqlalchemy import create_engine, MetaData, Table, Column
    
class __PostgresService:
    def __init__(self):
        self.__client = create_engine("postgresql://postgres@localhost:5432/database")
        metadata = MetaData(self.__client, schema="public")
        metadata.reflect(schema="public", only=["model"])
        self.__table = Table("training", metadata,
                Column("id", String, primary_key=True, nullable=False),
                Column("model_id", ForeignKey("model.id"), nullable=False),
                schema="api")
        metadata.create_all()

        postgres_service = __PostgresService()

默认情况下,MetaData.create_all() 会先检查 table 是否存在,然后再创建它们,但您也可以指定确切的 table 来创建:metadata.create_all(tables=[self.__table])