SQLAlchemy 2.0 文档
使用遗留的“backref”关系参数¶
注意
relationship.backref
关键字应被视为遗留,建议使用 relationship.back_populates
和明确的 relationship()
结构。使用单独的 relationship()
结构有以下优势:ORM 映射类将在构造时立即包含其属性,而不是作为延迟步骤,并且配置更直观,因为所有参数都是明确的。SQLAlchemy 2.0 中的新 PEP 484 功能也利用了属性在源代码中明确存在,而不是使用动态属性生成。
另请参阅
有关双向关系的一般信息,请参阅以下部分
处理 ORM 关联对象 - 在 SQLAlchemy 统一教程 中,介绍了使用 relationship.back_populates
的双向关系配置和行为概述。
双向关系中 save-update 级联的行为 - 关于双向 relationship()
行为的说明,涉及 Session
级联行为。
relationship.backref
关键字参数在 relationship()
结构中允许自动生成一个新的 relationship()
,它将自动添加到相关类的 ORM 映射中。然后,它将被放置在 relationship.back_populates
配置中,指向当前正在配置的 relationship()
,两个 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
参数,它引用多对多关联表,以及“连接”参数 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()
可以解释的形式,作为要应用于其创建的新关系的附加参数。
火焰! 龙和炼金术士 图像设计由 Rotem Yaari 创建并慷慨捐赠。
使用 Sphinx 7.2.6 创建。文档最后生成时间:2024 年 11 月 8 日星期五上午 08:41:19 EST