在 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")
在上述代码中,Parent
的 children
和 Child
的 parent
通过 back_populates
建立了双向关系。
3. backref
backref
是一个较老的参数,用于在目标模型中自动创建一个反向引用字段。它是一个字符串,表示在目标模型中创建的字段名称。
例如:
class Parent(Base):__tablename__ = 'parents'id = Column(Integer, primary_key=True)children = relationship("Child", backref="parent")
在 Child
模型中会自动创建一个名为 parent
的字段,指向 Parent
模型。
注意:backref
和 back_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. primaryjoin
和 secondaryjoin
这两个参数用于显式指定连接条件,通常在复杂的外键关系中使用。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
指定关联对象的排序方式。