使用遗留的 'backref' 关系参数¶
注意
relationship.backref
关键字应被视为遗留关键字,并且将 relationship.back_populates
与 explicit 一起使用
relationship()
结构。使用单独的 relationship()
结构具有优点,包括两个 ORM 映射类都将在构造类时预先包含其属性,而不是作为延迟步骤,并且由于所有参数都是显式的,因此配置更直接。SQLAlchemy 2.0 中的新 PEP 484 功能还利用了源代码中显式存在的属性,而不是使用动态属性生成。
另请参阅
有关双向关系的一般信息,请参阅以下部分:
使用 ORM 相关对象 - 在 SQLAlchemy Unified Tutorial 中,概述了使用 relationship.back_populates
的双向关系配置和行为
具有双向关系的保存-更新级联的行为 - 有关双向关系的说明()
行为。
relationship.backref
关键字参数
relationship()
结构允许自动生成一个新的 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
上建立了一个 Address
对象的集合,该集合在 User 上调用
它还
在 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 Unified Tutorial 中
在使用 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
condition 也被复制到新的 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” 足够聪明,知道在生成相反的 side 时,这两个参数也应该 “相反”。
指定 backref 参数¶
“backref” 的许多其他参数不是隐含的,并且
include 参数,如
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()
解释为要应用于它创建的新关系的附加参数。