This content originally appeared on DEV Community and was authored by Riko
Modeling relationships between tables is essential for representing data's real-world connections. Flask-SQLAlchemy provides two constructs to manage relationships: db.relationship and association_proxy.
There are three types of database relationships:
- One-to-many: One parent, many children
- One-to-one: One parent, one child
- Many-to-many: Many parents relate to many children
In this blog, I'll demonstrate how db.relationship and association_proxy are used in a database that has Meditations, Users, and Meditation Sessions.
- A user has many meditations through meditation sessions
- A meditation session has one meditation and one user
- A meditation has many users through meditation sessions
Here is the Python code with each class model and their relationships, including foreign key columns and serialize rules to prevent recursion:
class Meditation(db.Model, SerializerMixin):
__tablename__ = "meditations"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
duration = db.Column(db.Integer)
instructions = db.Column(db.String)
meditation_sessions = db.relationship('MeditationSession', back_populates='meditation', cascade='all, delete-orphan')
users = association_proxy('meditation_sessions', 'user', creator=lambda user_obj: MeditationSession(user=user_obj))
serialize_rules = ('-users.meditations', '-meditation_sessions.meditation',)
class User(db.Model, SerializerMixin):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, unique=True, nullable=False)
_password_hash = db.Column(db.String)
meditation_sessions = db.relationship('MeditationSession', back_populates='user', cascade='all, delete-orphan')
meditations = association_proxy('meditation_sessions', 'meditation', creator=lambda meditation_obj: MeditationSession(meditation=meditation_obj))
serialize_rules = ('-meditations.users', '-meditation_sessions.user')
class MeditationSession(db.Model, SerializerMixin):
__tablename__ = "meditation_sessions"
id = db.Column(db.Integer, primary_key=True)
completed_duration = db.Column(db.Integer)
rating = db.Column(db.Integer)
session_note = db.Column(db.String)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
meditation_id = db.Column(db.Integer, db.ForeignKey('meditations.id'))
user = db.relationship('User', back_populates='meditation_sessions')
meditation = db.relationship('Meditation', back_populates='meditation_sessions')
serialize_rules = ('-meditation.meditation_sessions', '-user.meditation_sessions')
db.relationship: establishing bi-directional relationships
db.relationship defines how tables or models relate to one another in Python objects. It works alongside foreign keys to create clear links and enable convenient querying and data manipulation.
Let's break down the relationship between a User and Meditation Session.
For a session, the relationship to a user is:
user = db.relationship('User', back_populates='meditation_sessions')
- Since a meditation session has only one user, the name of the property is singular
- The first argument passed to
db.relationshipis the target model class name (User) -
back_populatesis the name of the reciprocal relationship property on the User model (meditation_sessions)
Inversely, a user's relationship to a meditation session is:
meditation_sessions = db.relationship('MeditationSession', back_populates='user', cascade='all, delete-orphan')
- Since a user can have many meditation sessions, the name of the property is plural
- The first argument is the target model class name (
MeditationSession) - And
back_populatespoints back to theuserrelationship property we defined in Meditation Session, enabling a bidirectional link between the two models -
cascadespecifies how SQLAlchemy will handle child objects if the parent object were to disappear. There are several options that can be passed:-
allis a combination ofsave-update,merge, anddelete, meaning the child meditation sessions will be added to the database session, merged if the session contains duplicate objects, and deleted if the parent object is deleted -
delete-orphanwill delete a child if it is disassociated from its parent, meaning if a meditation session is removed fromuser.meditation_sessions, the meditation session will be deleted
-
association_proxy: establishing Many-to-Many relationships
association_proxy is a construct that allows a class to reach across an intermediary class in a many-to-many relationship. In our model, a user can have many meditations through meditation sessions, and a meditation can have many users through meditation sessions. Meditation Session is the intermediary class between Users and Meditations.
Let's break down the association proxy between User and Meditation.
For a user, the association to meditation is:
meditations = association_proxy('meditation_sessions', 'meditation', creator=lambda meditation_obj: MeditationSession(meditation=meditation_obj))
- Since this is a many-to-many relationship, the property name is plural (
meditations) - The first argument passed to
association_proxyspecifies the relationship property we defined above withdb.relationshipand intend to use as a connector (meditation_sessions) - The second argument (
meditation) indicates the name of the model we're connecting to - The
creatorparameter takes a function (an anonymous lambda in this case), which accepts an object of the other independent class and returns the corresponding object of the connecting class that made the connection possible- The lambda function creates a new intermediary
MeditationSessionobject when aMeditationis added to themeditationsassociation proxy -
meditation_objis an instance of theMeditationmodel passed in by theassociation_proxy -
MeditationSession(meditation=meditation_obj)creates a newMeditationSessionobject and sets itsmeditationrelationship to thatmeditation_obj - This new
MeditationSessioninstance acts as the link or bridge between theUserand theMeditation
- The lambda function creates a new intermediary
This content originally appeared on DEV Community and was authored by Riko
Riko | Sciencx (2025-10-25T14:24:34+00:00) Understanding Database Relationships in Flask-SQLAlchemy: `db.relationship` and `association_proxy`. Retrieved from https://www.scien.cx/2025/10/25/understanding-database-relationships-in-flask-sqlalchemy-db-relationship-and-association_proxy/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.