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

详解SQLAlchemy的函数relationship

在 SQLAlchemy 中,relationship 是一个非常重要的函数,用于定义模型之间的关系。它用于在 ORM 层面上表示数据库表之间的关联关系(如 1 对 1、1 对多和多对多)。relationship 的主要作用是提供一个高级接口,用于在模型之间导航和操作关联数据。

relationship 的基本用法

relationship 函数通常定义在模型类中,用于指定两个模型之间的关系。它的基本语法如下:

Python复制

relationship(argument, secondary=None, primaryjoin=None, secondaryjoin=None, backref=None, back_populates=None, uselist=True, order_by=False, lazy='select', viewonly=False, ...)

关键参数详解

1. argument

这是 relationship 函数的第一个位置参数,通常是一个字符串,表示目标模型的类名。例如:

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    children = relationship("Child")  # 指向 Child 模型
2. back_populates

用于双向关系的设置。它指定在目标模型中,哪个字段会反向引用当前模型。back_populates 是 SQLAlchemy 1.0 之后推荐的双向关系设置方式,替代了旧版本的 backref
例如:

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", back_populates="parent")

class Child(Base):
    __tablename__ = 'children'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parents.id'))
    parent = relationship("Parent", back_populates="children")

在上述代码中,ParentchildrenChildparent 通过 back_populates 建立了双向关系。

3. backref

backref 是一个较老的参数,用于在目标模型中自动创建一个反向引用字段。它是一个字符串,表示在目标模型中创建的字段名称。
例如:

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", backref="parent")

Child 模型中会自动创建一个名为 parent 的字段,指向 Parent 模型。

注意backrefback_populates 是互斥的,不能同时使用。back_populates 是更推荐的方式,因为它更清晰地表达了双向关系。

4. uselist

该参数用于指定关系是否为多对一或一对一。默认值为 True,表示多对一或一对多关系。如果设置为 False,则表示一对一关系。
例如:

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    child = relationship("Child", uselist=False)  # 一对一关系
5. secondary

用于多对多关系,指定关联表。关联表通常是一个 Table 对象,定义了两个模型之间的多对多关系。
例如:

association_table = Table('association', Base.metadata,
    Column('parent_id', Integer, ForeignKey('parents.id')),
    Column('child_id', Integer, ForeignKey('children.id'))
)

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", secondary=association_table, back_populates="parents")

class Child(Base):
    __tablename__ = 'children'
    id = Column(Integer, primary_key=True)
    parents = relationship("Parent", secondary=association_table, back_populates="children")
6. primaryjoinsecondaryjoin

这两个参数用于显式指定连接条件,通常在复杂的外键关系中使用。primaryjoin 指定主表的连接条件,secondaryjoin 指定目标表的连接条件。
例如:

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", primaryjoin="Parent.id == Child.parent_id")

class Child(Base):
    __tablename__ = 'children'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parents.id'))
7. lazy

该参数用于控制关联对象的加载策略。常见值包括:

  • select:默认值,表示在访问关联对象时,会自动执行一个 SELECT 查询。

  • joined:表示在加载主对象时,通过 JOIN 查询同时加载关联对象。

  • dynamic:表示返回一个查询对象,而不是直接加载关联对象,适合处理大量关联数据。

例如:

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", lazy="joined")  # 使用 JOIN 查询加载关联对象
8. order_by

用于指定关联对象的排序方式。它接受一个列对象或字符串,表示排序的依据。
例如:

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", order_by="Child.name")  # 按照 Child 的 name 字段排序
9. viewonly

该参数用于创建只读关系。如果设置为 True,则不能通过该关系进行数据的添加、删除或更新操作。
例如:

class Parent(Base):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", viewonly=True)  # 只读关系

总结

relationship 是 SQLAlchemy 中用于定义模型关系的核心函数,通过合理使用其参数,可以灵活地实现各种复杂的关系(如 1 对 1、1 对多和多对多)。以下是一些关键点:

  • 使用 back_populates 而非 backref,以更清晰地定义双向关系。

  • 通过 uselist 控制关系类型(一对一或一对多)。

  • 使用 secondary 指定多对多关系的关联表。

  • 通过 lazy 参数控制加载策略,优化性能。

  • 使用 order_by 指定关联对象的排序方式。


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

相关文章:

  • Vim 多窗口编辑及文件对比
  • STM32的HAL库开发---高级定时器
  • Golang的引用类型和指针
  • 深浅拷贝~
  • 自动化测试、压力测试、持续集成
  • 【LeetCode】152、乘积最大子数组
  • .net的一些知识点6
  • 【ESP32cam人脸识别开门及服务器端实战源码】
  • 回退 android studio emulator 的版本
  • 51单片机之使用Keil uVision5创建工程以及使用stc-isp进行程序烧录步骤
  • 【测试开发】Python+Django实现接口测试工具
  • docker 网络详解
  • 基于 llama-Factory 动手实践 Llama 全参数 SFT 和 LoRA SFT
  • 【C++】C++对C语言的扩充
  • 台湾精锐APEX减速机在半导体制造设备中的应用案例
  • matlab simulink 三级倒立摆LQR控制
  • 【GoLang】切片的面试知识点
  • 【Python深入浅出】Python3中os模块:开启系统交互的万能钥匙
  • 【Spring Boot】网页五子棋项目中遇到的困难及解决方法
  • 进阶数据结构——链式前向星
  • k8s集群外exporter怎么使用Prometheus监控
  • SQLAlchemy-2.0中模型定义和alembic的数据库迁移工具
  • 大语言模型遇上自动驾驶:AsyncDriver如何巧妙解决推理瓶颈?
  • 某咨询大数据解决方案介绍(32页PPT)
  • springboot+redis实现将树形结构存储到redis
  • python的ruff简单使用