SQLModel Operations & Relationships
SQLModel: Read, Update, Delete & Related Tables
Read Operations
Reading the First Result
The
results.first()
method is used to retrieve the first item from a query result.If the database query returns no results,
first()
will returnNone
.Example Code:
python def select_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.age < 25) results = session.exec(statement) hero = results.first() print("Hero:", hero)
Reading Exactly One Result
The
results.one()
method is used when you expect an exact single item to be returned from the database.If the query returns less than one item (zero items) or more than one item,
results.one()
will raise an error.Example Code:
python def select_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.age < 25) results = session.exec(statement) hero = results.one() print("Hero:", hero)
Selecting with where
Clause
The
where()
method is used to filter query results based on specified conditions.Example Code (filtering by ID):
python def select_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.id == 1) results = session.exec(statement) hero = results.first() print("Hero:", hero)
Selecting with get()
(Shorter Version for Primary Key)
The
session.get(Model, primary_key_value)
method provides a shorthand for retrieving a model instance by its primary key.It implicitly uses a
where
clause on the primary key.If no row is found with the given primary key,
get()
returnsNone
.Example Code:
python def select_heroes(): with Session(engine) as session: hero = session.get(Hero, 1) print("Hero:", hero)
Selecting All Results
The
results.all()
method retrieves all items matching the query statement.Example Code:
python def select_heroes(): with Session(engine) as session: statement = select(Hero) results = session.exec(statement) heroes = results.all() print(heroes)
Selecting with limit()
The
limit(N)
method restricts the number of results returned by the query to a maximum of N items.Example Code:
python def select_heroes(): with Session(engine) as session: statement = select(Hero).limit(3) results = session.exec(statement) heroes = results.all() print(heroes)
Selecting with offset()
and limit()
The
offset(N)
method skips the first N results before returning the remaining ones.It is often used in conjunction with
limit()
for pagination.Example Code (skipping 3, then taking the next 3):
python def select_heroes(): with Session(engine) as session: statement = select(Hero).offset(3).limit(3) results = session.exec(statement) heroes = results.all() print(heroes)
Example Code (getting the next 3 after the previous offset):
python def select_heroes(): with Session(engine) as session: statement = select(Hero).offset(6).limit(3) results = session.exec(statement) heroes = results.all() print(heroes)
Combining limit()
, offset()
, and where()
These methods can be chained together to apply multiple filtering and pagination criteria.
The order of
where()
,offset()
, andlimit()
matters:where()
applies first to filter the total set.offset()
then skips records from the filtered set.limit()
finally restricts the number of remaining records.
Example Code (finding heroes older than 32, skipping the first, then taking the next 2):
python def select_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.age > 32).offset(1).limit(2) results = session.exec(statement) heroes = results.all() print(heroes)
Create (Add More Data)
New instances of a SQLModel class are created and then added to the session using
session.add()
.session.commit()
persists these changes to the database.Example (creating multiple Hero instances):
def create_heroes(): hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson") hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador") hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48) hero_4 = Hero(name="Tarantula", secret_name="Natalia Roman-on", age=32) hero_5 = Hero(name="Black Lion", secret_name="Trevor Challa", age=35) hero_6 = Hero(name="Dr. Weird", secret_name="Steve Weird", age=36) hero_7 = Hero(name="Captain North America", secret_name="Esteban Rogelios", age=93)
with Session(engine) as session: session.add(hero_1) session.add(hero_2) session.add(hero_3) session.add(hero_4) session.add(hero_5) session.add(hero_6) session.add(hero_7) session.commit()
Update Operations
To update a row:
Retrieve the desired object(s) from the database.
Modify the attributes of the retrieved object(s).
Add the modified object(s) back to the session using
session.add()
(even if it's already in the session, this signals it as dirty).Commit the session using
session.commit()
.Optionally,
session.refresh(obj)
reloads the object's attributes from the database to reflect any changes made by the database (e.g., auto-updated timestamps, default values).
Example Code (updating a hero's age):
def update_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.name == "Spider-Boy") results = session.exec(statement) hero = results.one() print("Hero:", hero)
hero.age = 16 session.add(hero) session.commit() session.refresh(hero) print("Updated hero:", hero)
Delete Operations
To delete a row:
Retrieve the object to be deleted from the database.
Call
session.delete(obj)
with the retrieved object.Commit the session using
session.commit()
.
After
session.commit()
, the object is marked as deleted in the DB. Attempting to query it again will returnNone
(if usingfirst()
orget()
) or raise an error (if usingone()
).Example Code (deleting a hero):
def delete_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.name == "Spider-Youngster") results = session.exec(statement) hero = results.one() print("Hero: ", hero) session.delete(hero) session.commit()
print("Deleted hero:", hero) statement = select(Hero).where(Hero.name == "Spider-Youngster") results = session.exec(statement) hero = results.first() if hero is None: print("There's no hero named Spider-Youngster")
SQLModel: Related Tables
Defining Models with Foreign Keys
Related tables are established using
ForeignKey
fields in SQLModel classes.The
foreign_key
argument inField()
specifies the target table and its primary key (e.g.,"team.id"
).Important: The
foreign_key
string uses the actual database table name (usually lowercase and pluralized by default, or explicitly defined with__tablename__
), not the Python class name.Team Model Example:
from sqlmodel import Field, SQLModel, create_engine class Team(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) name: str = Field(index=True) headquarters: str # It's name "Team" here but is "team" in database
Hero Model Example (with
team_id
as Foreign Key):
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str = Field(index=True)
secret_name: str
age: int | None = Field(default=None, index=True)
team_id: int | None = Field(default=None, foreign_key="team.id")
Creating Database Tables
The
SQLModel.metadata.create_all(engine)
method generates all defined tables in the database.Example Code:
from app.core.db import engine # Assuming engine is defined elsewhere def create_db_and_tables(): SQLModel.metadata.create_all(engine) def main(): create_db_and_tables() if __name__ == "__main__": main()
Creating Data for Related Tables
First, create and commit instances of the