5.3 ORM
FastAPI does not come with a built-in ORM, but it works well with any ORM of your choice.
1. Common ORMs Used with FastAPI:
Section titled โ1. Common ORMs Used with FastAPI:โ1. SQLAlchemy (most popular)
Section titled โ1. SQLAlchemy (most popular)โ-
Mature, flexible, widely used in Python.
-
FastAPI works great with both:
- SQLAlchemy Core (manual SQL-style queries)
- SQLAlchemy ORM (class-based models and queries)
2. Tortoise ORM
Section titled โ2. Tortoise ORMโ- Async-native ORM.
- Simple and easy to use.
- Good fit if your entire FastAPI app is async.
3. Gino
Section titled โ3. Ginoโ- Async ORM designed for PostgreSQL.
- Lightweight, with a similar API to SQLAlchemy.
4. Pony ORM
Section titled โ4. Pony ORMโ- Unique syntax using Python generators.
- Less common, but can be used with FastAPI.
2. Example with SQLAlchemy:
Section titled โ2. Example with SQLAlchemy:โfrom sqlalchemy import Column, Integer, String, create_enginefrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.orm import sessionmaker
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL)SessionLocal = sessionmaker(bind=engine)Base = declarative_base()
# Define modelclass User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True)FastAPI itself doesnโt manage the database layer โ you manually create the session, models, and dependency injection.
====================================================
Hereโs a complete working example of using FastAPI with SQLAlchemy based on your model. This includes:
- Database setup
- Model definition
- Dependency injection
- Create/read endpoints
๐ Project Structure (flat, simple)
Section titled โ๐ Project Structure (flat, simple)โmain.pytest.db (auto-created by SQLite)๐ main.py
Section titled โ๐ main.pyโfrom fastapi import FastAPI, Depends, HTTPExceptionfrom sqlalchemy import Column, Integer, String, create_enginefrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.orm import sessionmaker, Sessionfrom pydantic import BaseModel
# -------------------------------# Database setup# -------------------------------DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})SessionLocal = sessionmaker(bind=engine, autocommit=False, autoflush=False)Base = declarative_base()
# -------------------------------# SQLAlchemy model# -------------------------------class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True)
# Create the table(s)Base.metadata.create_all(bind=engine)
# -------------------------------# Pydantic schemas# -------------------------------class UserCreate(BaseModel): name: str
class UserOut(BaseModel): id: int name: str
class Config: orm_mode = True
# -------------------------------# FastAPI app# -------------------------------app = FastAPI()
# Dependency for DB sessiondef get_db(): db = SessionLocal() try: yield db finally: db.close()
# -------------------------------# Routes# -------------------------------
# Create a new user@app.post("/users/", response_model=UserOut)def create_user(user: UserCreate, db: Session = Depends(get_db)): db_user = User(name=user.name) db.add(db_user) db.commit() db.refresh(db_user) return db_user
# Get a user by ID@app.get("/users/{user_id}", response_model=UserOut)def read_user(user_id: int, db: Session = Depends(get_db)): user = db.query(User).filter(User.id == user_id).first() if user is None: raise HTTPException(status_code=404, detail="User not found") return user
# Get all users@app.get("/users/", response_model=list[UserOut])def read_users(db: Session = Depends(get_db)): return db.query(User).all()โถ๏ธ Run the app:
Section titled โโถ๏ธ Run the app:โuvicorn main:app --reload๐ Access the API Docs
Section titled โ๐ Access the API DocsโGo to: http://127.0.0.1:8000/docs
FastAPI will generate interactive Swagger docs automatically!
๐ Summary
Section titled โ๐ SummaryโThis example shows:
- How to use SQLAlchemy with FastAPI.
- How to define models and schemas.
- How to connect routes with database operations using dependency injection.
Let me know if you want this with async support or with PostgreSQL instead.
=========================================
Sure! Letโs go through the FastAPI + SQLAlchemy code line by line and explain every section in detail. This will help you understand how it all fits together to create a fully working REST API.
๐ง 1. Imports
Section titled โ๐ง 1. Importsโfrom fastapi import FastAPI, Depends, HTTPExceptionfrom sqlalchemy import Column, Integer, String, create_enginefrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.orm import sessionmaker, Sessionfrom pydantic import BaseModelFastAPI: The main class for creating the API app.Depends: Used for dependency injection.HTTPException: Used to raise errors with HTTP status codes.Column, Integer, String: SQLAlchemy column types.create_engine: Creates the database engine.declarative_base: Used to define the base class for models.sessionmaker: Creates database sessions.Session: Type for database session.BaseModel: Pydantic class for request/response data validation.
๐ข๏ธ 2. Database Configuration
Section titled โ๐ข๏ธ 2. Database ConfigurationโDATABASE_URL = "sqlite:///./test.db"- Defines the database URL.
- Using SQLite (file-based DB) stored as
test.dbin the current directory.
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})create_engine: Connects SQLAlchemy to the database.connect_args={"check_same_thread": False}: Required for SQLite to allow multiple threads to access the DB (needed for FastAPI).
SessionLocal = sessionmaker(bind=engine, autocommit=False, autoflush=False)SessionLocal: A factory for creating new DB sessions.autocommit=False,autoflush=False: Makes session more controlled (explicit commits).
Base = declarative_base()- Base class used to define SQLAlchemy models.
๐ค 3. Define SQLAlchemy Model
Section titled โ๐ค 3. Define SQLAlchemy Modelโclass User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True)-
Defines a
Usertable with:id: Primary key (auto-increment).name: String field.
-
__tablename__ = "users": The actual table name in the database.
๐๏ธ 4. Create Table(s)
Section titled โ๐๏ธ 4. Create Table(s)โBase.metadata.create_all(bind=engine)- Automatically creates the tables in the DB based on your model definitions.
๐ฆ 5. Define Pydantic Schemas
Section titled โ๐ฆ 5. Define Pydantic SchemasโPydantic models validate input and control output structure.
class UserCreate(BaseModel): name: str- This is the input schema used when a user is being created (POST).
class UserOut(BaseModel): id: int name: str
class Config: orm_mode = True- This is the response schema (what the API returns).
orm_mode = True: Allows FastAPI to return SQLAlchemy objects directly (theyโre not dicts by default).
๐ 6. Create the FastAPI App
Section titled โ๐ 6. Create the FastAPI Appโapp = FastAPI()- This is the API app object. Youโll pass this to
uvicornto run the server.
๐ 7. Database Dependency
Section titled โ๐ 7. Database Dependencyโdef get_db(): db = SessionLocal() try: yield db finally: db.close()- A dependency function used with
Depends. - It creates a new DB session for each request and closes it after use.
๐ 8. API Routes
Section titled โ๐ 8. API Routesโ๐ธ Create a User
Section titled โ๐ธ Create a Userโ@app.post("/users/", response_model=UserOut)def create_user(user: UserCreate, db: Session = Depends(get_db)): db_user = User(name=user.name) db.add(db_user) db.commit() db.refresh(db_user) return db_user- POST endpoint at
/users/. - Accepts a JSON body with a
namefield. - Creates a
Userobject, adds it to the session, commits, refreshes (gets theid), and returns the new user.
๐ธ Get a User by ID
Section titled โ๐ธ Get a User by IDโ@app.get("/users/{user_id}", response_model=UserOut)def read_user(user_id: int, db: Session = Depends(get_db)): user = db.query(User).filter(User.id == user_id).first() if user is None: raise HTTPException(status_code=404, detail="User not found") return user- GET endpoint at
/users/{user_id}. - Queries for the user by ID.
- If not found, returns a 404 error.
๐ธ Get All Users
Section titled โ๐ธ Get All Usersโ@app.get("/users/", response_model=list[UserOut])def read_users(db: Session = Depends(get_db)): return db.query(User).all()- GET endpoint at
/users/. - Returns all users in the DB as a list.
๐งช 9. Run the App
Section titled โ๐งช 9. Run the Appโuvicorn main:app --reload- Starts the FastAPI server.
--reloadmeans auto-restart on code change (useful during development).
๐ 10. Interactive API Docs
Section titled โ๐ 10. Interactive API DocsโVisit: http://127.0.0.1:8000/docs
- FastAPI generates Swagger UI automatically.
- You can test all endpoints here directly in your browser.
โ Summary
Section titled โโ SummaryโThis app:
- Connects to a SQLite database.
- Defines a
Usermodel/table. - Provides API endpoints to create and fetch users.
- Uses SQLAlchemy for ORM and Pydantic for input/output validation.
- Automatically generates interactive documentation.
Let me know if youโd like to add PUT, DELETE, or async support.