What is the difference between backref and back_populates in SQLAlchemy?
As I was working on a project I encountered an error when I used back_populates, upon further research I discovered that I made a minor mistake of not using back_populates property correctly. Am writing this to help anyone not to make the same mistake. Let's dive in!
back_populates
When you use back_populates
you are supposed to refer to the relationship in both the Parent class and the Child class. This is the mistake I made, I forgot to include the relationship in the Parent class although I included it in the Child class and it got me debugging the entire day.
Example
The following example shows a use case of back_populates
:
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.orm import declarative_base, relationship
Base = declarative_base()
class Parent(Base):
"""
A class representing the 'parent' table.
Attributes:
id (int): The primary key of the Parent table.
children (Relationship): One-to-many relationship with Child table.
"""
__tablename__ = "parent"
id = Column(Integer, primary_key=True)
children = relationship("Child", back_populates="parent")
class Child(Base):
"""
A class representing the 'child' table.
Attributes:
id (int): The primary key of the Child table.
parent_id (int): Foreign key referencing the Parent table.
parent (Relationship): Many-to-one relationship with Parent table.
"""
__tablename__ = "child"
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey("parent.id"))
parent = relationship("Parent", back_populates="children")
Note:
back_populates
requires explicit creation of relationship in both Parent and Child classes.
backref
When using backref
you only need to create a relationship in one class. The ForeinKey
must be included in the Child class regardless of the placement of relationship.
Example
The following example shows a use case of backref
:
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.orm import declarative_base, relationship
Base = declarative_base()
class Parent(Base):
"""
A class representing the 'parent' table.
Attributes:
id (int): The primary key of the Parent table.
"""
__tablename__ = "parent"
id = Column(Integer, primary_key=True)
class Child(Base):
"""
A class representing the 'child' table.
Attributes:
id (int): The primary key of the Child table.
parent_id (int): Foreign key referencing the Parent table.
parent (Relationship): Many-to-one relationship with Parent table.
"""
__tablename__ = "child"
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey("parent.id"))
parent = relationship("Parent", backref="children")
backref
is a shortcut for creating a bidirectional relationship between the Parent and the Child class in one place.
Verdict
Both backref
and back_populates
can be used to establish bidirectional relationships between two tables in an ORM (Object-Relational Mapping) setup. If you only need a simple relationship and don't need to make changes on both sides often, backref
might be simpler. If you want more control and explicitness, or if you need to modify both sides frequently, back_populates
might be a better choice.