SQLAlchemy 2.0 文档
使用旧式的 ‘backref’ 关系参数¶
注意
应将 relationship.backref
关键字视为旧式用法,并且应优先使用 relationship.back_populates
和显式的 relationship()
构造。使用单独的 relationship()
构造具有诸多优势,包括两个 ORM 映射类都将在类构造时预先包含其属性,而不是作为延迟步骤,并且配置更直接,因为所有参数都是显式的。SQLAlchemy 2.0 中的新 PEP 484 功能也利用了源代码中显式存在的属性,而不是使用动态属性生成。
另请参阅
有关双向关系的常规信息,请参阅以下章节
使用 ORM 相关对象 - 在 SQLAlchemy 统一教程 中,概述了使用 relationship.back_populates
的双向关系配置和行为
使用双向关系进行保存-更新级联的行为 - 关于 relationship()
在 Session
级联行为方面的双向行为的注释。
relationship.backref
关键字参数在 relationship()
构造上允许自动生成一个新的 relationship()
,该关系将自动添加到相关类的 ORM 映射中。然后,它将被放置到针对当前正在配置的 relationship()
的 relationship.back_populates
配置中,并且两个 relationship()
构造相互引用。
从以下示例开始
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import DeclarativeBase, relationship
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "user"
id = mapped_column(Integer, primary_key=True)
name = mapped_column(String)
addresses = relationship("Address", backref="user")
class Address(Base):
__tablename__ = "address"
id = mapped_column(Integer, primary_key=True)
email = mapped_column(String)
user_id = mapped_column(Integer, ForeignKey("user.id"))
上述配置在 User
上建立了一个名为 User.addresses
的 Address
对象集合。它还在 Address
上建立了一个 .user
属性,该属性将引用父 User
对象。使用 relationship.back_populates
,它等效于以下内容
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import DeclarativeBase, relationship
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "user"
id = mapped_column(Integer, primary_key=True)
name = mapped_column(String)
addresses = relationship("Address", back_populates="user")
class Address(Base):
__tablename__ = "address"
id = mapped_column(Integer, primary_key=True)
email = mapped_column(String)
user_id = mapped_column(Integer, ForeignKey("user.id"))
user = relationship("User", back_populates="addresses")
User.addresses
和 Address.user
关系的行为是,它们现在以双向方式运行,表明关系一侧的更改会影响另一侧。有关此行为的示例和讨论,请参见 SQLAlchemy 统一教程 中的 使用 ORM 相关对象。
Backref 默认参数¶
由于 relationship.backref
生成了一个全新的 relationship()
,因此默认情况下,生成过程将尝试在新 relationship()
中包含与原始参数相对应的参数。例如,下面是一个 relationship()
,其中包含一个 自定义连接条件,该条件还包括 relationship.backref
关键字
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import DeclarativeBase, relationship
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "user"
id = mapped_column(Integer, primary_key=True)
name = mapped_column(String)
addresses = relationship(
"Address",
primaryjoin=(
"and_(User.id==Address.user_id, Address.email.startswith('tony'))"
),
backref="user",
)
class Address(Base):
__tablename__ = "address"
id = mapped_column(Integer, primary_key=True)
email = mapped_column(String)
user_id = mapped_column(Integer, ForeignKey("user.id"))
生成 “backref” 时,relationship.primaryjoin
条件也会被复制到新的 relationship()
中
>>> print(User.addresses.property.primaryjoin)
"user".id = address.user_id AND address.email LIKE :email_1 || '%%'
>>>
>>> print(Address.user.property.primaryjoin)
"user".id = address.user_id AND address.email LIKE :email_1 || '%%'
>>>
其他可传递的参数包括引用多对多关联表的 relationship.secondary
参数,以及 “join” 参数 relationship.primaryjoin
和 relationship.secondaryjoin
;“backref” 足够智能,知道在生成另一侧时,这两个参数也应该被 “反转”。
指定 Backref 参数¶
许多其他 “backref” 的参数不是隐式的,包括 relationship.lazy
, relationship.remote_side
, relationship.cascade
和 relationship.cascade_backrefs
等参数。对于这种情况,我们使用 backref()
函数代替字符串;这将存储一组特定的参数,这些参数将在生成新的 relationship()
时传递给它
# <other imports>
from sqlalchemy.orm import backref
class User(Base):
__tablename__ = "user"
id = mapped_column(Integer, primary_key=True)
name = mapped_column(String)
addresses = relationship(
"Address",
backref=backref("user", lazy="joined"),
)
在上面,我们仅在 Address.user
侧放置了 lazy="joined"
指令,表明当对 Address
进行查询时,应自动进行与 User
实体的连接,这将填充每个返回的 Address
的 .user
属性。backref()
函数将我们给它的参数格式化为接收 relationship()
解释的形式,作为应用于其创建的新关系的附加参数。
flambé! 龙和 The Alchemist 图像设计由 Rotem Yaari 创作并慷慨捐赠。
使用 Sphinx 7.2.6 创建。文档最后生成时间:2025年3月11日 02:40:17 PM EDT