我有三张桌子:
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 个多对多表
嗯,看起来就像在任一关系中添加
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()
我真的不明白为什么。