2016-10-05 14 views
19

私は、このガイド以下のSQLAlchemyの関係の例を試してみてください。私はこのコードいつsqlalchemy back_populatesを使用する必要がありますか?

#!/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) 

を持ってBasic Relationship Patterns

これはよく動作しますが、ガイドでは、モデルがあるべきと言う:

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が必要なのはなぜですか?どちらを使うべきですか?

答えて

37

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を使用して、あなたがback_populatesを使用しない場合は、1つのも修正を修正するようにrelationshipさん別に、そして、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のは、これらの二つのフィールドは、現在関連している知っている、と他が更新されると各を更新します。 backrefを使用するとこれも実行されます。 back_populatesを使用すると、すべてのクラスでリレーションシップを定義したい場合に便利です。逆参照によってフィールドを定義する他のクラスを見るのではなく、モデルクラスを見ているだけのすべてのフィールドを簡単に見ることができます。

関連する問題