在SQLAlchemy中通过双属于多定义关系

问题描述 投票:0回答:1

我有三张桌子:

Item
Shelve
Cabinet

A

Cabinet
有许多
Shelve
Shelve
有许多
Item

Item
    id: int
    shelve_id: int

Shelve
    id: int
    cabinet_id: int

Cabinet:
    id: id

我希望将

Cabinet
Item
列表建立方便的关系:

class Cabinet(DeclarativeBase):
    # ...
    items: Mapped[List["Item"]] = relationship()

但是,这会产生错误,无法找到

Cabinet
Item
之间的关系。我可以理解,因为关系并不明显,
Shelve
将充当一种连接表。

如何在 SQLAlchemy 中完成此任务?

我正在阅读有关 relationships 的文档,但我不确定哪个适用。我需要二次加入吗?
我发现的其他问题涉及双重多对多关系,这听起来不同:SQLAlchemy 关系通过 2 个多对多表

python sqlalchemy
1个回答
0
投票

嗯,看起来就像在任一关系中添加

secondary="shelves"
一样简单。与我正在寻找的关系完整的模型:

class Cabinet(DeclarativeBase):
    __tablename__ = "cabinets"

    id: Mapped[int] = mapped_column(primary_key=True)

    shelves: Mapped[List["Shelve"]] = relationship(back_populates="cabinet")

    # Also provide indirect association:
    items: Mapped[List["Item"]] = relationship(
        secondary="shelves",
        back_populates="cabinet",
        viewonly=True,  # Prevent SAWArning
    )


class Shelve(DeclarativeBase):
    __tablename__ = "shelves"

    id: Mapped[int] = mapped_column(primary_key=True)
    cabinet_id: Mapped[int] = mapped_column(ForeignKey("cabinets.id"))

    items: Mapped[List["Item"]] = relationship(back_populates="shelve")
    cabinet: Mapped["Cabinet"] = relationship(back_populates="shelves")


class Item(DeclarativeBase):
    __tablename__ = "items"

    id: Mapped[int] = mapped_column(primary_key=True)
    shelve_id: Mapped[int] = mapped_column(ForeignKey("shelves.id"))

    shelve: Mapped["Shelve"] = relationship(back_populates="items")

    # Also provide indirect association:
    cabinet: Mapped["Item"] = relationship(
        secondary="shelves",
        back_populates="items",
        viewonly=True,  # Prevent SAWArning
    )

我仍然很困惑,因为如果没有

viewonly=True
,我会收到 SA 的警告:

SAWarning:关系“Cabinet.items”将复制列 Cabinet.id 到 列shelf.cabinet_id,与关系冲突: 'Shelves.cabinet'(将 Cabinets.id 复制到 Shelves.cabinet_id), 'Cabinets.shelves'(将abinets.id复制到shelf.cabinet_id)。如果 这不是本意,请考虑这些关系是否应该 与 back_populates 链接,或者如果 viewonly=True 应应用于 一个或多个(如果它们是只读的)。对于不太常见的情况 外键约束部分重叠,orm.foreign() 可以使用注释来隔离应该写入的列 向。要消除此警告,请添加参数 'overlaps="shelves,cabinet"' 到 'Cabinet.items' 关系。 (此警告的背景:https://sqlalche.me/e/20/qzyx)(这 警告源自

configure_mappers()
进程,该进程是 自动调用以响应用户启动的操作。)

我真的不明白为什么。

© www.soinside.com 2019 - 2024. All rights reserved.