このガイドに従って SQLAlchemy リレーションの例を試した場合:基本的な関係パターン
このコードを持っています
#!/usr/bin/env python
# encoding: utf-8
from sqlalchemy import create_engine
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base(bind=engine)
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Child")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
parent = relationship("Parent")
Base.metadata.create_all()
p = Parent()
session.add(p)
session.commit()
c = Child(parent_id=p.id)
session.add(c)
session.commit()
print "children: {}".format(p.children[0].id)
print "parent: {}".format(c.parent.id)
うまく動作しますが、ガイドではモデルは次のようにする必要があると書かれています:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
**children = relationship("Child", back_populates="parent")**
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
**parent = relationship("Parent", back_populates="children")**
back_populates
私の例では または が必要ないのはなぜですかbackref
? どちらか一方をいつ使用すればよいですか?
ベストアンサー1
使用する場合、backref
2 番目のテーブルで関係を宣言する必要はありません。
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Child", backref="parent")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
もしあなたが〜ならないを使用してbackref
、relationship
を個別に定義した場合、 を使用しないとback_populates
、sqlalchemy は関係を接続する方法を認識できず、一方を変更するともう一方も変更されます。
relationship
したがって、を個別に定義したが引数を指定しなかった例では、back_populates
1 つのフィールドを変更しても、トランザクション内の他のフィールドは自動的に更新されません。
>>> parent = Parent()
>>> child = Child()
>>> child.parent = parent
>>> print(parent.children)
[]
フィールドが自動的に入力されなかったのがわかりますかchildren
?
ここで、back_populates
引数を指定すると、sqlalchemy はフィールドを接続します。
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Child", back_populates="parent")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
parent = relationship("Parent", back_populates="children")
それで、私たちは
>>> parent = Parent()
>>> child = Child()
>>> child.parent = parent
>>> print(parent.children)
[Child(...)]
Sqlalchemy は、これら 2 つのフィールドが関連していることを認識し、もう一方のフィールドが更新されると、それぞれを更新します。 usingbackref
でも同じことが行われることに注意してください。 using はback_populates
、すべてのクラスで関係を定義する場合に便利です。これにより、backref を介してフィールドを定義する他のクラスを確認する必要がなくなり、モデル クラスをざっと見るだけですべてのフィールドを簡単に確認できます。