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])。‌‌
相关推荐
大可不必了9 小时前
03 函数定义和调用
开发语言·python
承渊政道10 小时前
【Python编程—从入门到实践】(记分与闯关:用Python+Pygame,打造越战越精彩的太空大战!)
开发语言·python·pycharm·游戏程序·pygame
爱学习的程序媛10 小时前
Python常用框架梳理
开发语言·后端·python·ai·web·后端框架·python框架
imgsq10 小时前
GESP Python 一到四级:备考路线与真题特点
python·青少年编程
eggwyw12 小时前
Anaconda安装卸载的详细流程指南
开发语言·python
2601_9679791212 小时前
纯手写:Python安装pip完整教程,搞了几小时,终于成功
python·教程·pip·安装·包管理
Norna12 小时前
缓存文件从没写出来:一个 .json 被当成目录用了
python
aifannihao15 小时前
AI 学习第 14 课:CNN 训 6 轮卡在 0.5352,数据没打乱
pytorch·python·深度学习·cnn·学习路线
yuyuxun115 小时前
协同过滤的校园二手物品智能推荐系统的设计与实现 毕业设计-附源码40082
javascript·vue.js·spring boot·python·数据分析·django·课程设计
如夏倾城16 小时前
百度文心(容易被忽略的好用AI)使用方式
人工智能·python·百度·语言模型·dubbo