Using the legacy ‘backref’ relationship parameter¶
..note:: relationship.backref
キーワードはレガシーと考えるべきであり、明示的な relationship()
構文を持つ relationship.back_populates
の使用が優先されるべきです。個々の relationship()
構文を使用することは、両方のORMマップされたクラスが、遅延ステップとしてではなく、クラスが構築されるときに事前に属性を含めることを含む利点を提供し、すべての引数が明示的であるため、設定がより簡単になります。SQLAlchemy 2.0の新しい PEP 484 機能も、動的な属性生成を使用するのではなく、ソースコード内に明示的に存在する属性を利用します。
See also
双方向関係の一般的な情報については、次の項を参照してください。
Working with ORM Related Objects - SQLAlchemy Unified Tutorial で、 relationship.back_populates
を使用した双方向の関係の設定と動作の概要を示します
Behavior of save-update cascade with bi-directional relationships -Session
のカスケード動作に関する、双方向の relationship()
の動作についての注意です。
relationship()
構文の relationship.backref
キーワード引数を使用すると、関連するクラスのORMマッピングに自動的に追加される新しい relationship()
を自動的に生成できます。その後、設定されている現在の relationship()
に対して、両方の relationship()
構文が互いを参照しながら、 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", 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.addresses
と呼ばれる User
上に Address
オブジェクトのコレクションを確立します。また、親の User
オブジェクトを参照する Address
上に .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
の関係の動作は、 双方向 の方法で動作するようになりました。これは、関係の一方の側の変更が他方に影響を与えることを示しています。この動作の例と説明は、 Working with ORM Related Objects の SQLAlchemy Unified Tutorial にあります。
Backref Default Arguments¶
relationship.backref
はまったく新しい relationship()
を生成するので、生成プロセスはデフォルトで、元の引数に対応する新しい relationship()
に対応する引数を含めようとします。例として、以下は custom join condition を含む 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”は、反対側を生成するときにこれら2つの引数も”反転”する必要があることを十分に理解しています。
Specifying Backref Arguments¶
“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"),
)
Where above, we placed a lazy="joined"
directive only on the Address.user
side, indicating that when a query against Address
is made, a join to the User
entity should be made automatically which will populate the .user
attribute of each returned Address
. The backref()
function formatted the arguments we gave it into a form that is interpreted by the receiving relationship()
as additional arguments to be applied to the new relationship it creates.
上記では、 lazy="joined"
ディレクティブを Address.user
側にのみ配置しました。これは、 Address
に対するクエリが作成されたときに、返された各 Address
の .user
属性を設定する User
エンティティへの結合が自動的に行われることを示しています。 backref()
関数は、我々が与えた引数を、それが作成する新しい関係に適用される追加引数として受信側の relationship()
によって解釈される形式にフォーマットしました。