Help us understand the problem. What is going on with this article?

SQLAlchemyのback_populatesとbackrefの違いとどちらも使わない場合

More than 3 years have passed since last update.

SQLAlchemyのback_populatesとbackrefって何がどう違うの?っていうかどっちも書かないとどうなるの?という話。

結論から書くと、

(1)backrefを使用した場合
双方向のリレーションを自動的に組んでくれる。

(2)back_populatesを使用した場合
双方向のリレーションを自分で組む必要がある。

(3)back_populatesもbackrefも使用しない場合
トランザクション中、逆方向のフィールドが自動更新されない。

ということになる。

では、具体例を見ていく。
例としてEventモデルとTicketモデルを考える。
1つのEventは複数のTicketをもっている、One to Manyの関係。

backrefを使用した場合

class Event(Base):
    __tablename__ = 'event'
    id = Column(Integer, primary_key=True)
    title = Column(String(255))
    tickets = relationship("Ticket",backref="event")

class Ticket(Base):
    __tablename__ = 'ticket'
    id = Column(Integer,primary_key=True)
    title = Column(String(255))
    value = Column(Integer)
    event_id = Column(Integer,ForeignKey('event.id'))
event = Event(title="test")
ticket = Ticket(title="test_ticket",value=5000)
event.tickets = [ticket]

event.tickets #Ticket Objects
ticket.event #Event Object

back_populatesを使用した場合

back_populatesを使用する場合は、双方向のリレーションを組まないと動作しない。

class Event(Base):
    __tablename__ = 'event'
    id = Column(Integer, primary_key=True)
    title = Column(String(255))
    tickets = relationship("Ticket",back_populates="event")

class Ticket(Base):
    __tablename__ = 'ticket'
    id = Column(Integer,primary_key=True)
    title = Column(String(255))
    value = Column(Integer)
    event_id = Column(Integer,ForeignKey('event.id'))
    event = relationship("Event",back_populates="tickets")
event = Event(title="test")
ticket = Ticket(title="test_ticket",value=5000)
event.tickets = [ticket]

event.tickets #Ticket Objects
ticket.event #Event Object

どちらも使用しない場合

class Event(Base):
    __tablename__ = 'event'
    id = Column(Integer, primary_key=True)
    title = Column(String(255))
    tickets = relationship("Ticket")

class Ticket(Base):
    __tablename__ = 'ticket'
    id = Column(Integer,primary_key=True)
    title = Column(String(255))
    value = Column(Integer)
    event_id = Column(Integer,ForeignKey('event.id'))
    event = relationship("Event")
event = Event(title="test")
ticket = Ticket(title="test_ticket",value=5000)
event.tickets = [ticket]

event.tickets #Ticket Objects
ticket.event #None

この場合、ticket→eventがNoneになっている。
つまり、トランザクション内ではticketにeventが紐付いていない事がわかる。
勿論、トランザクション終了後(eventオブジェクトをインサートした後)なら双方向で紐付いている。

event = self.session.query(Event).filter(Event.id==1).one()
ticket = self.session.query(Ticket).filter(Ticket.id==1).one()

event.tickets #Ticket Objects
ticket.event #Event Object
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away