SQLAlchemy 中的关系和关联代理

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

我们正在使用 FastAPI 和 SQLAlchemy 来提供服务(最新版本)。我们有一个“静态”表,该表预先填充了数据,不应插入其中。 varchar id 和名称的非常基本的模式。

我们有另一个表,它有两个引用该表的字段,一个是 id 列表,另一个是对象列表。尽管“静态”表不知道动态表,但本质上存在多对多关系。我创建了一个映射表来支持这一点。

这是模型对象(简化):

a_to_type_mapping = Table(
    "a_to_type_mapping",
    Base.metadata,
    Column("a_id", ForeignKey("a.id"), primary_key=True),
    Column("type_id", ForeignKey("type.id"), primary_key=True),
)
class A(Base):
    __tablename__ = "a"
    id: Mapped[str] = mapped_column(unique=True, index=True, primary_key=True)
    types: Mapped[List["Type"]] = relationship(lazy="selectin", secondary=a_to_type_mapping)
    type_ids: AssociationProxy[List[str]] = association_proxy("types","id")

class Type(Base):
    __tablename__ = "type"
    id: Mapped[str] = mapped_column(index=True, primary_key=True, unique=True)
    name: Mapped[str] = mapped_column(unique=True, nullable=False)

这似乎工作正常,除非我在 pytests 中插入新对象的部分,例如:

A(
    id="SomeId"
    types=[Type(id="2",name="Two")]
)

基本上是试图说新的 A 与该类型相关联。但在测试过程中,它尝试将 Type id=2 插入“type”表中,当然会遇到唯一的约束错误(Type(id="2", name="Two") 之前已作为设置插入)

这难道不是实现这种关系的正确方式吗?本质上,我希望 Type 表是只读的,但仍然允许创建新的 A 对象并引用该表(在 ids 列表和关联对象列表中)。

谢谢!

sqlalchemy relationship
1个回答
0
投票

我不确定您的测试实际上是什么样子,但您应该首先获取类型。如果您有静态表,另一个选择是使用您在测试期间导入的固定装置来填充它。

from sqlalchemy.sql import select

def test_create_a(db_session):
    type_2 = db_session.scalars(select(Type).where(id="2")).first()
    a = A(
        id="SomeId"
        types=[type2]
    )
    db_session.add(a)
    db_session.flush()
© www.soinside.com 2019 - 2024. All rights reserved.