How to create one-to-one relationships with declarative
I have two tables, foo
and bar
, and I want foo.bar_id
to link to bar
. The catch is that this is a one-way one-to-one relationship. bar
must not know anything about foo
. For every foo, there will be one and only one bar
.
Ideally, after selecting a foo, I could do something like this:
myfoo.bar.whatever = 5
How to accomplish this?
Solution 1:
The documentation explains this nicely:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child = relationship("Child", uselist=False, backref="parent")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
OR
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'))
child = relationship("Child", backref=backref("parent", uselist=False))
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
Solution 2:
If you want a true one-to-one relationship, you also have to use the "uselist=False" in your relationship definition.
bar_id = Column(Integer, ForeignKey(Bar.id))
bar = relationship(Bar, uselist=False)
Solution 3:
I think if it is a truly one to one relationship we should add a uniqueness constraint to foreign key so another parent can not have other parent child!! Like this:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'), unique=True)
child = relationship("Child", backref=backref("parent", uselist=False))
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
Solution 4:
It turns out this is actually quite easy. In your Foo model:
bar_id = Column(Integer, ForeignKey(Bar.id))
bar = relationship(Bar)