SQLModel 多对多关系实现详解

SQLModel 多对多关系实现详解

sqlmodel SQL databases in Python, designed for simplicity, compatibility, and robustness. sqlmodel 项目地址: https://gitcode.com/gh_mirrors/sq/sqlmodel

多对多关系简介

在关系型数据库中,多对多关系是一种常见的数据关联方式。它表示一个实体可以与多个其他实体相关联,反之亦然。在SQLModel中,我们可以通过中间表(关联表)来实现这种关系。

核心模型定义

中间表模型

class HeroTeamLink(SQLModel, table=True):
    team_id: Optional[int] = Field(
        default=None, foreign_key="team.id", primary_key=True
    )
    hero_id: Optional[int] = Field(
        default=None, foreign_key="hero.id", primary_key=True
    )

这个中间表模型HeroTeamLink定义了英雄和团队之间的关联关系。它包含两个字段:

  • team_id: 外键关联到Team表的id,同时也是主键的一部分
  • hero_id: 外键关联到Hero表的id,同时也是主键的一部分

这种复合主键的设计确保了每个英雄-团队组合的唯一性。

团队模型

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="teams", link_model=HeroTeamLink)

团队模型定义了:

  • 基本字段:id、name(有索引)、headquarters
  • 关系字段:heroes,通过Relationship指定与Hero模型的多对多关系
    • back_populates="teams"表示双向关系
    • link_model=HeroTeamLink指定了中间表模型

英雄模型

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

    teams: List[Team] = Relationship(back_populates="heroes", link_model=HeroTeamLink)

英雄模型定义了:

  • 基本字段:id、name(有索引)、secret_name、age(可选且有索引)
  • 关系字段:teams,同样通过Relationship建立与Team模型的多对多关系

数据库初始化

sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"

engine = create_engine(sqlite_url, echo=True)

def create_db_and_tables():
    SQLModel.metadata.create_all(engine)

这部分代码完成了:

  1. 指定SQLite数据库文件位置
  2. 创建数据库引擎,设置echo=True以便查看SQL语句
  3. 定义函数创建所有表结构

数据操作示例

def create_heroes():
    with Session(engine) as session:
        # 创建团队
        team_preventers = Team(name="Preventers", headquarters="Sharp Tower")
        team_z_force = Team(name="Z-Force", headquarters="Sister Margaret's Bar")

        # 创建英雄并关联团队
        hero_deadpond = Hero(
            name="Deadpond",
            secret_name="Dive Wilson",
            teams=[team_z_force, team_preventers],
        )
        hero_rusty_man = Hero(
            name="Rusty-Man",
            secret_name="Tommy Sharp",
            age=48,
            teams=[team_preventers],
        )
        hero_spider_boy = Hero(
            name="Spider-Boy", secret_name="Pedro Parqueador", teams=[team_preventers]
        )
        
        # 添加到会话并提交
        session.add(hero_deadpond)
        session.add(hero_rusty_man)
        session.add(hero_spider_boy)
        session.commit()

        # 刷新对象以获取数据库生成的值
        session.refresh(hero_deadpond)
        session.refresh(hero_rusty_man)
        session.refresh(hero_spider_boy)

        # 打印结果
        print("Deadpond:", hero_deadpond)
        print("Deadpond teams:", hero_deadpond.teams)
        print("Rusty-Man:", hero_rusty_man)
        print("Rusty-Man Teams:", hero_rusty_man.teams)
        print("Spider-Boy:", hero_spider_boy)
        print("Spider-Boy Teams:", hero_spider_boy.teams)

这个函数展示了如何:

  1. 创建团队和英雄实例
  2. 通过列表直接建立多对多关联
  3. 使用会话管理数据库操作
  4. 提交事务并刷新对象状态
  5. 验证关联关系是否正确建立

实际应用建议

  1. 索引优化:模型中的索引设置合理,name和age字段都有索引,适合查询场景
  2. 事务管理:使用上下文管理器(with语句)确保会话正确关闭
  3. 数据验证:在实际应用中,可以添加更多的数据验证逻辑
  4. 性能考虑:对于大型数据集,可能需要考虑批量插入优化

总结

通过SQLModel实现多对多关系非常直观,主要步骤包括:

  1. 定义中间表模型
  2. 在主模型中通过Relationship建立关联
  3. 指定link_model指向中间表
  4. 使用back_populates建立双向关系

这种设计既保持了代码的简洁性,又提供了强大的关系管理能力,是处理复杂数据关联的理想选择。

sqlmodel SQL databases in Python, designed for simplicity, compatibility, and robustness. sqlmodel 项目地址: https://gitcode.com/gh_mirrors/sq/sqlmodel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倪姿唯Kara

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值