LoginSignup
75
36

More than 5 years have passed since last update.

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

Posted at

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
75
36
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
75
36