Python 学习笔记:SQLModel 使用外键关联查询数据

在 SQLModel 里用 foreign_key 主要是两步:在"多方"的模型字段上通过 Field(foreign_key="表名.列名") 建立外键,再用 Relationship() 定义模型间的关系属性,方便 Python 层面直接访问关联数据。‌‌

🧱 基础用法:定义一对多关系

以一个团队(Team)拥有多个英雄(Hero)为例:

  1. ‌定义 Team 模型("一方") ‌:和普通模型一样,主键用 primary_key=True。
  2. ‌定义 Hero 模型("多方") ‌:在 team_id 字段上用 foreign_key="team.id"指定外键,team 是数据库中的表名(小写),不是模型类名 Team。
  3. ‌添加 Relationship 属性 ‌:在两边分别用 Relationship(back_populates="...") 建立双向关系,这样就能通过 hero.team 或 team.heroes 直接访问关联数据。
python 复制代码
from typing import Optional, List
from sqlmodel import Field, SQLModel, Relationship

class Team(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    headquarters: str

    heroes: List["Hero"] = Relationship(back_populates="team")

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    secret_name: str
    age: Optional[int] = None
    team_id: Optional[int] = Field(default=None, foreign_key="team.id")

    team: Optional[Team] = Relationship(back_populates="heroes")

🔑 关键点说明

  • ‌外键字符串格式 ‌:必须是 "表名.列名",比如 "team.id",这里用的是数据库表名(小写),不是 Python 类名。
  • ‌可空性自动推断 ‌:如果字段类型是 Optional[int],SQLModel 会自动把该列设为可空(无 NOT NULL 约束),表示"英雄可以不属于任何战队"。
  • ‌底层机制 ‌:foreign_key 最终会被包装成 SQLAlchemy 的 ForeignKey 对象,在数据库中生成 FOREIGN KEY... REFERENCES... 约束。

🔗 关联查询

建立关系后,查询就很方便了:

python 复制代码
from sqlmodel import Session, select

# 查询英雄,直接访问关联的团队
with Session(engine) as session:
    statement = select(Hero).where(Hero.name == "Rusty-Man")
    hero = session.exec(statement).first()
    if hero and hero.team:
        print(f"Team: {hero.team.name}")

# 反向查询:从团队找所有英雄
with Session(engine) as session:
    statement = select(Team).where(Team.name == "Preventers")
    team = session.exec(statement).first()
    if team:
        for hero in team.heroes:
            print(f" - {hero.name}")

⚠️ 注意

  • 如果不需要在 Python 层面通过 .team 或 .heroes 访问关联数据,只用 foreign_key 建立数据库外键约束也是可以的,但要用 JOIN 来查询关联数据。
  • 删除关联数据时,可以通过 ondelete="CASCADE" 或 ondelete="RESTRICT" 控制数据库层面的行为;ondelete="SET NULL" 要求该字段必须可空(Optional[int])。‌‌
相关推荐
专业程序开发源1 小时前
springboot社区养老系统44071-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·php·课程设计
在世修行2 小时前
干货:左右分栏调试工具设计
python·调试设计
零基础1232 小时前
DeepSeek V4.1 Flash (Batch) 的性能测试与应用
经验分享·python·语言模型·vllm
Yyyyyy~2 小时前
【Anaconda】安装
人工智能·python
LOVE️YOU2 小时前
Python 函数名、函数对象与“把函数作为参数传递”
开发语言·python
2601_957883842 小时前
2026年9月:雷神笔记本售后相关资讯
python·电脑
天赐范式3 小时前
天赐范式第185天:让漂变开始定量——扫N看选择主导边界
python·信噪比·数字生命·天赐范式·动态运行时·种群大小·遗传漂变
Jo乔戈里3 小时前
免费本地搜图软件
图像处理·python·搜索引擎·ai
for_ever_love__3 小时前
字符串处理——f-string、切片与正则,清洗文本的第一把刀
python·大模型·虚拟环境