当前位置: 首页 > article >正文

如何使用sqlalchemy的orm模式构建表结构1对1,1对多,多对多的关系

在 SQLAlchemy 的 ORM 模式中,可以通过定义类和关系来构建表结构,实现一对一、一对多和多对多的关系。以下是具体的实现方式:

1. 一对一关系(One-to-One)

一对一关系是指一个记录与另一个记录之间存在唯一对应关系。在 SQLAlchemy 中,可以通过 relationshipuselist=False 来实现。

示例代码
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker

Base = declarative_base()

class Person(Base):
    __tablename__ = 'persons'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    # 定义一对一关系
    passport = relationship("Passport", uselist=False, back_populates="person")

class Passport(Base):
    __tablename__ = 'passports'
    id = Column(Integer, primary_key=True)
    passport_number = Column(String)
    person_id = Column(Integer, ForeignKey('persons.id'))
    # 反向引用
    person = relationship("Person", back_populates="passport")

# 创建数据库引擎和会话
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# 添加数据
person = Person(name="Alice")
passport = Passport(passport_number="123456789")
person.passport = passport
session.add(person)
session.commit()

# 查询
person = session.query(Person).first()
print(person.name, person.passport.passport_number)

2. 一对多关系(One-to-Many)

一对多关系是指一个记录可以与多个记录相关联。在 SQLAlchemy 中,可以通过 relationshipForeignKey 来实现。

示例代码
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker

Base = declarative_base()

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    # 定义一对多关系
    children = relationship("Child", back_populates="parent")

class Child(Base):
    __tablename__ = 'children'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    parent_id = Column(Integer, ForeignKey('parents.id'))
    # 反向引用
    parent = relationship("Parent", back_populates="children")

# 创建数据库引擎和会话
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# 添加数据
parent = Parent(name="John")
child1 = Child(name="Alice")
child2 = Child(name="Bob")
parent.children.append(child1)
parent.children.append(child2)
session.add(parent)
session.commit()

# 查询
parent = session.query(Parent).first()
for child in parent.children:
    print(parent.name, child.name)

3. 多对多关系(Many-to-Many)

多对多关系是指多个记录可以与多个记录相关联。在 SQLAlchemy 中,需要通过一个关联表来实现。

示例代码
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker

Base = declarative_base()

# 关联表
association_table = Table('association', Base.metadata,
    Column('left_id', Integer, ForeignKey('left.id')),
    Column('right_id', Integer, ForeignKey('right.id'))
)

class Left(Base):
    __tablename__ = 'left'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    # 定义多对多关系
    rights = relationship("Right", secondary=association_table, back_populates="lefts")

class Right(Base):
    __tablename__ = 'right'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    # 反向引用
    lefts = relationship("Left", secondary=association_table, back_populates="rights")

# 创建数据库引擎和会话
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# 添加数据
left1 = Left(name="Left1")
left2 = Left(name="Left2")
right1 = Right(name="Right1")
right2 = Right(name="Right2")

left1.rights.append(right1)
left1.rights.append(right2)
left2.rights.append(right1)

session.add_all([left1, left2, right1, right2])
session.commit()

# 查询
left = session.query(Left).first()
for right in left.rights:
    print(left.name, right.name)

总结

  • 一对一:通过 relationshipuselist=False 实现。

  • 一对多:通过 relationshipForeignKey 实现。

  • 多对多:通过一个关联表和 secondary 参数实现。


SQLAlchemy 的 ORM(对象关系映射)模式通过将数据库表映射到 Python 类,并利用类之间的关系来构建数据库结构。以下是上述三种关系实现的原理:

1. 一对一关系(One-to-One)

一对一关系是最简单的关系,表示两个表之间一对一的关联。通常通过ForeignKeyrelationship来实现。

原理:
  1. 外键约束(ForeignKey)

    • 在一个表中定义一个外键(外键列),关联到另一个表的主键。

    • 例如,在Passport表中定义person_id作为外键,关联到Person表的主键id

    person_id = Column(Integer, ForeignKey('persons.id'))
  2. 双向关系(relationship)

    • 在两个类之间使用relationship属性,通过back_populates参数实现双向引用。

    • 例如,Person类中的passport属性和Passport类中的person属性相互引用。

    person = relationship("Person", back_populates="passport")
    passport = relationship("Passport", uselist=False, back_populates="person")
    • 参数uselist=False表示该关系是一对一而非一对多。

  3. 数据库结构

    • 数据库中会生成两个表:personspassports

    • passports表中有一个外键列person_id,指向persons表的id

结果:

通过这种结构,每个Person对象只能有一个Passport对象,反之亦然。


2. 一对多关系(One-to-Many)

一对多关系是数据库中最常见的关系,表示一个记录可以关联到多个其他记录。

原理:
  1. 外键约束(ForeignKey)

    • 在“多”的一方定义一个外键,关联到“一”的一方的主键。

    • 例如,在Child表中定义parent_id作为外键,关联到Parent表的主键id

    parent_id = Column(Integer, ForeignKey('parents.id'))
  2. 双向关系(relationship)

    • 在“一”的一方使用relationship属性,指定back_populates参数。

    • 在“多”的一方也使用relationship属性,通过外键关联到“一”的一方。

    # Parent类的一对多关系
    children = relationship("Child", back_populates="parent")
    
    # Child类的反向关系
    parent = relationship("Parent", back_populates="children")
  3. 数据库结构

    • 数据库中会生成两个表:parentschildren

    • children表中有一个外键列parent_id,指向parents表的id

结果:

通过这种结构,每个Parent对象可以关联多个Child对象,但每个Child对象只能关联一个Parent对象。


3. 多对多关系(Many-to-Many)

多对多关系表示多个记录可以同时关联到多个其他记录。这种关系通常通过一个关联表(中间表)来实现。

原理:
  1. 关联表(Association Table)

    • 定义一个中间表,包含两个外键,分别关联到两个主表的主键。

    • 例如,association_table包含left_idright_id两个外键,分别关联到leftright表的主键。

    association_table = Table('association', Base.metadata,
        Column('left_id', Integer, ForeignKey('left.id')),
        Column('right_id', Integer, ForeignKey('right.id'))
    )
  2. 双向关系(relationship)

    • 在两个主表中使用relationship属性,通过secondary参数指定关联表。

    • 使用back_populates参数实现双向引用。

    # Left类的多对多关系
    rights = relationship("Right", secondary=association_table, back_populates="lefts")
    
    # Right类的反向关系
    lefts = relationship("Left", secondary=association_table, back_populates="rights")
  3. 数据库结构

    • 数据库中会生成三个表:leftrightassociation

    • association表中包含两个外键列,分别指向leftright表的主键。

结果:

通过这种结构,Left对象和Right对象可以相互关联,并且一个Left对象可以关联多个Right对象,反之亦然。


总结

  1. “One-to-One”

    • 通过外键和relationship实现一对一关系,uselist=False确保关系为一对一。

  2. “One-to-Many”

    • 通过外键和relationship实现一对多关系,“一”的一方包含一个列表,用于存储“多”的一方的多个对象。

  3. “Many-to-Many”

    • 通过中间表和relationshipsecondary参数实现多对多关系,中间表存储两个表之间的关联。


http://www.kler.cn/a/535419.html

相关文章:

  • 嵌入式八股文面试题(一)C语言部分
  • VMware Win10下载安装教程(超详细)
  • openssl 中 EVP_aes_256_gcm() 函数展开
  • MyBatis Plus 输出完整 SQL(带参数)的 3 种方案
  • Javascript 日期计算如何实现当前日期加一天或者减去一天
  • RabbitMQ:python基础调用
  • 如何打造一个更友好的网站结构?
  • Vue组件开发——进阶篇
  • OS10 固件更新步骤-U 盘方式
  • SQL 中的谓词逻辑
  • PHP商会招商项目系统小程序
  • CentOS服务器部署Docker+Jenkins持续集成环境
  • 微信小程序调用企业微信客户服务插件联通企业微信客服
  • 【Elasticsearch】geotile grid聚合
  • Python Bug修复案例分析:列表切片引发的内存泄漏问题
  • DeepSeek R1 Distill Llama 70B(免费版)API使用详解
  • CSS Position(定位)详解及举例说明
  • C#迭代器和Unity的Coroutine原理
  • Vue el-input密码输入框 按住显示密码,松开显示*;阻止浏览器密码回填,自写密码输入框;校验输入非汉字内容;文本框聚焦到内容末尾;
  • 68.浏览文件并选择文件 C#例子 WPF例子
  • 在K8S中,如何解决SVC容灾问题?
  • 想品客老师的第十二天:异步和promise
  • 图片PDF区域信息批量提取至Excel,基于QT和阿里云api的实现方案
  • Unity 简易的UI框架
  • C和Rust的一些区别
  • C中静态库和动态库的使用