You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SQLModel中通过两层外键建立A与C的直接关联?

问题分析

你遇到的错误核心原因是:A.c 这个 Relationship 没有对应的直接外键字段,SQLModel 无法自动推断 A 和 C 的关联逻辑——当前 A 与 C 仅通过 B 表间接关联,没有直接的外键约束。

解决方案

方案一:混合属性快速访问(只读场景)

无需修改数据库结构,给 A 类添加一个混合属性,通过已有的 B 关联间接获取 C 对象:

from sqlalchemy.ext.hybrid import hybrid_property

class A(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    b_id: int | None = Field(default=None, foreign_key="b.id")

    b: 'B' = Relationship(back_populates='as')

    @hybrid_property
    def c(self) -> 'C':
        return self.b.c if self.b else None

class B(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    c_id: int | None = Field(default=None, foreign_key='c.id')

    as: list[A] = Relationship(back_populates='b')
    c: 'C' = Relationship(back_populates='bs')

class C(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    
    bs: list[B] = Relationship(back_populates='c')

使用时直接通过 a.c 即可获取对应的 C 对象,此方式仅适用于读取操作,无法通过 A 直接修改 C 的关联。

方案二:带手动关联条件的只读 Relationship(支持查询过滤)

如果需要通过 A 直接查询 C(例如 select(A).join(A.c)),可以用 viewonly=True 结合 primaryjoin 手动指定关联逻辑:

class A(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    b_id: int | None = Field(default=None, foreign_key="b.id")

    b: 'B' = Relationship(back_populates='as')
    c: 'C' = Relationship(
        viewonly=True,
        primaryjoin="A.b_id == B.id and B.c_id == C.id",
        uselist=False  # 匹配当前结构:1个A对应1个B,1个B对应1个C
    )

class B(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    c_id: int | None = Field(default=None, foreign_key='c.id')

    as: list[A] = Relationship(back_populates='b')
    c: 'C' = Relationship(back_populates='bs')

class C(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    
    bs: list[B] = Relationship(back_populates='c')

primaryjoin 明确告知 ORM 关联路径,viewonly=True 表示该关系仅用于查询读取,不支持写入操作。若你的业务中存在一个 A 对应多个 C 的场景,需将 uselist 改为 True,并将 c 的类型改为 list[C]。

内容的提问来源于stack exchange,提问作者Michael Piccirillo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:21:11