We use SQLAlchemy with FastAPI to easily connect and work with databases in a clean and organized way.
SQLAlchemy setup with FastAPI
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
FastAPI
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db" engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base()
create_engine connects to the database.
SessionLocal creates sessions to talk to the database.
Examples
test.db.FastAPI
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"connect_args is needed for SQLite to allow multiple threads.FastAPI
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})FastAPI
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
FastAPI
Base = declarative_base()
Sample Program
This example shows how to set up SQLAlchemy with FastAPI. It creates a User model, connects to a SQLite database, and adds a POST endpoint to create users.
FastAPI
from fastapi import FastAPI, Depends from sqlalchemy import Column, Integer, String from sqlalchemy.orm import Session from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db" engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True) Base.metadata.create_all(bind=engine) app = FastAPI() def get_db(): db = SessionLocal() try: yield db finally: db.close() @app.post("/users/") async def create_user(name: str, db: Session = Depends(get_db)): user = User(name=name) db.add(user) db.commit() db.refresh(user) return {"id": user.id, "name": user.name}
Important Notes
Always close the database session after use to avoid connection leaks.
Use Base.metadata.create_all(bind=engine) once to create tables in the database.
Use dependency injection (Depends) in FastAPI to get a database session in your path functions.
Summary
SQLAlchemy helps connect FastAPI apps to databases easily.
Set up engine, session, and base to start using SQLAlchemy.
Use sessions to add, read, update, or delete data safely.
Practice
1. What is the main purpose of
SessionLocal in a FastAPI app using SQLAlchemy?easy
Solution
Step 1: Understand the role of SessionLocal
SessionLocal is a session factory that creates new database sessions for each request to ensure safe and isolated database operations.Step 2: Differentiate from other components
The database schema is defined by models, the engine connects to the database, and user data is unrelated to SessionLocal.Final Answer:
To create a new database session for each request -> Option AQuick Check:
SessionLocal creates new sessions per request [OK]
Hint: SessionLocal always means a new session per request [OK]
Common Mistakes:
- Confusing SessionLocal with engine
- Thinking SessionLocal defines schema
- Assuming SessionLocal stores user data
2. Which of the following is the correct way to create the SQLAlchemy engine in FastAPI?
easy
Solution
Step 1: Identify the common FastAPI SQLite engine setup
FastAPI tutorials often use SQLite with the URL 'sqlite:///./test.db' and the argument to allow multiple threads.Step 2: Check options for correctness
engine = create_engine('sqlite:///./test.db', connect_args={'check_same_thread': False}) matches the typical FastAPI SQLite setup with connect_args to avoid threading errors.Final Answer:
engine = create_engine('sqlite:///./test.db', connect_args={'check_same_thread': False}) -> Option AQuick Check:
SQLite engine with check_same_thread=False [OK]
Hint: SQLite needs check_same_thread=False in FastAPI [OK]
Common Mistakes:
- Omitting connect_args causing threading errors
- Using wrong database URL format
- Confusing in-memory with file-based SQLite
3. Given this FastAPI SQLAlchemy session usage, what will
print(user.name) output?
from sqlalchemy.orm import Session
def get_user(db: Session, user_id: int):
return db.query(User).filter(User.id == user_id).first()
user = get_user(db=session, user_id=1)
print(user.name)medium
Solution
Step 1: Understand the query behavior
The query filters User by id=1 and returns the first match or None if not found.Step 2: Analyze the print statement
If a user with id=1 exists, user.name prints the name; otherwise, user is None and accessing name would error.Final Answer:
The name of the user with id 1 -> Option BQuick Check:
Query returns user object [OK]
Hint: Query.first() returns object or None; here user exists [OK]
Common Mistakes:
- Assuming print outputs None without checking user
- Expecting an error without verifying user exists
- Confusing filter with filter_by syntax
4. Identify the error in this FastAPI SQLAlchemy session usage:
def create_user(db: Session, user: UserCreate):
db_user = User(name=user.name, email=user.email)
db.add(db_user)
# Missing db.commit()
return db_usermedium
Solution
Step 1: Check session usage for saving data
Adding an object to the session requires calling db.commit() to persist changes to the database.Step 2: Verify other parts of the code
db.add() is correct, User model import is assumed, and returning the new user is expected.Final Answer:
Missing call to db.commit() to save changes -> Option CQuick Check:
db.commit() needed after db.add() [OK]
Hint: Always commit after adding to session [OK]
Common Mistakes:
- Forgetting db.commit() after db.add()
- Using db.insert() instead of db.add()
- Returning wrong type from function
5. You want to set up SQLAlchemy with FastAPI to support multiple database types (SQLite, PostgreSQL) using environment variables. Which approach correctly configures the engine and session?
hard
Solution
Step 1: Use environment variable for database URL
Reading DATABASE_URL from environment allows flexible switching between databases.Step 2: Create engine with the URL and bind sessionmaker
Pass the URL to create_engine, then bind the engine to sessionmaker to create SessionLocal.Final Answer:
Use DATABASE_URL env var, pass it to create_engine, then create SessionLocal with sessionmaker(bind=engine) -> Option DQuick Check:
Env var URL + engine + sessionmaker(bind=engine) [OK]
Hint: Always bind engine to sessionmaker using env var URL [OK]
Common Mistakes:
- Hardcoding URLs reduces flexibility
- Not binding engine to sessionmaker causes errors
- Passing URL to sessionmaker instead of create_engine
