Skip to main content

Learning Objectives

By the end of this chapter, you will be able to:
  • Understand why ORMs are used.
  • Explain what Object Relational Mapping (ORM) is.
  • Understand the overall SQLAlchemy workflow.
  • Identify the major SQLAlchemy components.
  • Explain how Python objects are stored and retrieved from a database.

Topics Covered

In this module, you’ll learn:
  1. Introduction to ORM
  2. Building Your First SQLAlchemy Application
  3. CRUD Operations
  4. Retrieving Results
  5. ORM Relationships
Try Yourself: 💻 VS Code | 🚀 Colab | 📥 Download
Verify Solutions: 💻 VS Code | 🚀 Colab | 📥 Download

Working Without an ORM

A relational database understands only SQL. Whenever an application needs to store, retrieve, update, or delete data, the application must send SQL statements to the database. For example, to retrieve all students:
To insert a new student:
As applications grow, writing and maintaining SQL for every database operation becomes repetitive and difficult.

Working With an ORM

With an ORM, we work with Python classes and objects instead of writing SQL for most database operations. To insert a new student:
To retrieve all students:
Notice that we never wrote an SQL query. SQLAlchemy automatically generates the required SQL, sends it to the database, retrieves the results, and converts them back into Python objects. This allows us to focus on writing Python instead of manually writing SQL.

What is an ORM?

ORM (Object Relational Mapping) is a technique that maps Python objects to database tables. It allows us to work with: Think of an ORM as a translator between Python and a relational database.
Throughout this workshop, we’ll use SQLAlchemy ORM, one of the most popular ORM libraries in Python.

The Big Picture

Before learning the individual components, let’s understand the complete workflow.

Writing Data (INSERT / UPDATE / DELETE)

Reading Data (SELECT)

Notice the important role of SQLAlchemy.
  • We write Python code.
  • SQLAlchemy converts it into SQL.
  • The database executes the SQL.
  • SQLAlchemy converts the returned rows back into Python objects.
We’ll learn each step of this workflow throughout this module.

Understanding the Components

Now let’s understand the responsibility of each component.

Engine

The Engine is the starting point of every SQLAlchemy application. It knows:
  • Which database to connect to.
  • How to establish the connection.
  • How to send SQL statements.
Think of the Engine as the gateway to the database.

Session

The Session is used to interact with the database. It allows us to:
  • Add new objects
  • Retrieve objects
  • Update objects
  • Delete objects
  • Commit or rollback transactions
Think of the Session as your conversation with the database.

ORM Model

An ORM model is a Python class that represents a database table.
Each object created from this class represents one row in the table.

SQLAlchemy

SQLAlchemy acts as the translator. When we write Python code,
SQLAlchemy generates SQL.
When the database returns rows,
SQLAlchemy converts them into Python objects.

Database

The database stores the data and executes SQL statements. It understands SQL, not Python objects.

Putting Everything Together

Summary

In this chapter, you learned:
  • Why ORMs are needed.
  • What Object Relational Mapping (ORM) is.
  • How SQLAlchemy translates Python code into SQL.
  • The complete workflow for reading and writing data.
  • The role of the Engine, Session, ORM Model, SQLAlchemy, and the Database.
In the next chapter, we’ll start building this workflow by creating our first Engine, connecting to a database, defining our first ORM model, and creating our first table.

Building Your First SQLAlchemy ORM Application

Learning Objectives

By the end of this chapter, you will be able to:
  • Create a SQLAlchemy project.
  • Connect to a SQLite database.
  • Define an ORM model.
  • Create database tables.
  • Create a Session.
  • Insert data into the database.

Project Setup

Create a new project.
Initialize the project.
Install SQLAlchemy.
Project structure
Throughout this chapter, we’ll gradually build the same main.py.

Step 1 — Create the Engine

Every SQLAlchemy application starts by creating an Engine. The Engine knows which database to connect to. Import create_engine.
Create a Database URL.
Create the Engine.

Workflow

At this stage,
  • Engine is created.
  • No database operations have happened yet.
Current application

Step 2 — Create the Declarative Base

Every ORM model inherits from a common Base class. Import DeclarativeBase.
Create the Base class.

Workflow

SQLAlchemy uses the Base class to keep track of all ORM models. Current application

Step 3 — Create an ORM Model

An ORM model represents a database table. Import the required modules.
Create the model.

Mapping

SQL Equivalent
Current application

Step 4 — Create Database Tables

Create all tables.

What happens?

Note: For SQLite, the database file is created automatically if it doesn’t already exist. SQLAlchemy then creates the tables. For databases like PostgreSQL or MySQL, the database must already exist before connecting.
Current application

Step 5 — Create a Session

A Session is used to interact with the database. Import Session.
Create the Session.

Workflow

Think of the Session as your conversation with the database.

Step 6 — Insert a Record

Create a Python object.
Add the object to the Session.
Save the changes.
Refresh the object.
Display the generated ID.

Workflow

Generated SQL

Complete Application

Run the application.
Output ?
Open students.db using the SQLite extension. You should see:

Summary

Congratulations! 🎉 You have built your first SQLAlchemy ORM application. You learned how to:
  • Create an Engine.
  • Create a Declarative Base.
  • Define an ORM Model.
  • Create database tables.
  • Create a Session.
  • Insert data into the database.

CRUD Operations with SQLAlchemy ORM

CRUD stands for:
  • C – Create (INSERT)
  • R – Read (SELECT)
  • U – Update (UPDATE)
  • D – Delete (DELETE)
These are the four fundamental database operations performed using SQLAlchemy ORM.

Create (INSERT)

SQL

SQLAlchemy ORM

If you need the auto-generated values (such as the primary key), refresh the object.

Workflow

Read (SELECT)

Retrieve All Records

SQL

SQLAlchemy ORM

Retrieve by Primary Key

SQL

SQLAlchemy ORM

Retrieve the First Record

SQL

SQLAlchemy ORM

Workflow

Update (UPDATE)

Step 1 – Retrieve the Object

Step 2 – Modify the Object

Step 3 – Save the Changes

Complete Example

SQL

SQLAlchemy ORM

Workflow

Delete (DELETE)

Step 1 – Retrieve the Object

Step 2 – Delete the Object

Step 3 – Save the Changes

Complete Example

SQL

SQLAlchemy ORM

Workflow

CRUD Summary

Complete CRUD Example

SQL SELECT vs SQLAlchemy ORM

Retrieving Results in SQLAlchemy

After building a query using select(), you need to decide how you want to retrieve the results. SQLAlchemy provides different methods depending on whether you expect one object, multiple objects, or a single value.

Result Retrieval Methods

all()

Returns all matching records.
Result
Use when you want every matching record.

first()

Returns only the first matching record.
Result
or
Use when only the first matching record is required.

one()

Returns exactly one record.
Raises an exception if:
  • No record is found.
  • More than one record is found.
Use when you are certain exactly one record exists.

one_or_none()

Returns one record or None.
Returns
  • One object
  • None
Raises an exception if multiple records are found. Use when the record may or may not exist.

get()

Retrieves a record using its primary key.
Returns
or
Use get() only when searching by the primary key.

scalar()

Returns a single value. Example:
Result
Commonly used with:
  • COUNT()
  • SUM()
  • AVG()
  • MIN()
  • MAX()

scalars()

Returns ORM objects (or the first selected column) from a query. Example
Equivalent to
Use scalars() when retrieving ORM objects.

Quick Reference

Choosing the Right Method

ORM Relationships

In real-world applications, a single table is rarely enough to represent all the required data. Instead, multiple tables work together by establishing relationships between them. For example, in a Blog application:
  • A user can write multiple blog posts.
  • Every blog post belongs to one author.
  • A blog post can have multiple tags.
  • Every comment belongs to a blog post.
Instead of duplicating data across tables, relational databases connect tables using Primary Keys and Foreign Keys.

Why Relationships?

Suppose we store author information inside every blog post.
This causes several problems.
  • Duplicate data
  • Wasted storage
  • Difficult updates
  • Risk of inconsistent data
Instead, store author information only once.
Now the author details exist only once, making the database normalized and easier to maintain.

Primary Key vs Foreign Key

Every table has a Primary Key, which uniquely identifies each row. A Foreign Key stores the primary key value of another table.
Here,
  • Users.id is the Primary Key.
  • BlogPosts.author_id is the Foreign Key.

Types of Relationships

One-to-One (1:1)

One record is associated with exactly one record in another table. Examples
  • User → Profile
  • Employee → Passport
  • Student → Identity Card

One-to-Many (1:N)

One record can have multiple related records. This is the most common relationship. Example One author can write many blog posts.
Only the child table stores the foreign key.

Many-to-One (N:1)

This is simply the reverse direction of One-to-Many. Many blog posts belong to one author.
Although conceptually different, SQLAlchemy implements One-to-Many and Many-to-One together.

Many-to-Many (M:N)

Many records on one side are related to many records on the other side. Example
Examples
  • Students ↔ Courses
  • Users ↔ Roles
  • Blog Posts ↔ Tags
  • Movies ↔ Actors
Many-to-Many relationships always require an association table.

Relationship in Our Blog Application

Our application contains two tables.
One author can create multiple blog posts.
The relationship is therefore
One User → Many Blog Posts

User Roles

Our application stores both Authors and Admins inside the same users table.
The role determines permissions. Author
  • Create posts
  • Update own posts
  • Delete own posts
Admin
  • View all posts
  • Update any post
  • Delete any post
  • Manage users
Notice that roles do not affect the database relationship. Both Admin and Author are simply users. The relationship remains
Authorization is handled by the application logic, not by the database relationship.

Relationship in SQLAlchemy

SQLAlchemy models relationships in two different ways.

Database Relationship

The database only understands foreign keys.
This creates the actual database constraint.

ORM Relationship

Python objects need an object reference. For that, SQLAlchemy provides relationship().
and
Now SQLAlchemy understands that these two models are connected.

Complete User Model


Complete BlogPost Model


How SQLAlchemy Uses Relationships

Unlike SQL, SQLAlchemy lets us navigate related objects directly. Instead of writing joins, we simply access attributes.

Get all posts written by a user

Returns

Get the author of a blog post

Returns

Creating Relationships

Instead of assigning the foreign key manually,
you can assign the object itself.
SQLAlchemy automatically updates the foreign key during session.commit(). Similarly,
automatically sets
This synchronization is handled by the ORM.

Understanding back_populates

back_populates connects both relationship properties.
Without back_populates, each relationship behaves independently. With back_populates:
  • Updating one side updates the other.
  • Both objects remain synchronized.
  • Navigation works in both directions.

Database Relationship vs ORM Relationship

Both work together. The database guarantees referential integrity, while SQLAlchemy provides convenient object navigation.

Practice

To reinforce what you’ve learned in this section, practice with the interactive follow-along notebook:

Follow-Along Practice

Practice creating SQLAlchemy engines, declaring ORM Base models, running CRUD operations, and building relationships between tables.💻 VS Code | 🚀 Colab | 📥 Download

Summary

  • Relationships connect tables using foreign keys.
  • Primary keys uniquely identify rows.
  • Foreign keys reference another table’s primary key.
  • SQLAlchemy models relationships using relationship().
  • One-to-Many is the most common relationship in REST APIs.
  • back_populates connects both sides of the relationship.
  • SQLAlchemy lets you navigate relationships using Python objects instead of writing SQL joins.
  • User roles (Author/Admin) determine permissions but do not change the database relationship.
  • The database manages data integrity, while SQLAlchemy provides an object-oriented interface to work with related data.