FastAPI Tutorial for Complete Beginners
A step-by-step guide covering install, setup, CRUD APIs, params, and PostgreSQL — written
for someone new to both FastAPI and Python.
0. Python & pip basics (since you’re new to Python)
pip = Python’s package manager (like npm for Node).
Difference from Node: Node installs packages into a node_modules folder inside your
project automatically. Python does not do this by default — pip installs packages into
your Python installation’s site-packages folder globally, which is shared across all
projects.
This is why Python projects use a virtual environment (venv) — a self-contained folder
that acts like your project’s own private node_modules , holding its own copies of
packages and its own Python interpreter.
Where things live:
[Link] Python (no venv) Python (with venv)
/usr/lib/pythonX/site- ./venv/lib/pythonX/site-
./node_modules/
packages/ (global, shared) packages/ (local to project)
Always use a venv per project. It avoids version conflicts between projects, just like
node_modules isolates each Node project.
1. Install & Setup
Step 1 — Check Python is installed
python3 --version
Step 2 — Create a project folder + virtual environment
mkdir fastapi-demo && cd fastapi-demo
python3 -m venv venv
Step 3 — Activate the venv
# Mac/Linux
source venv/bin/activate
# Windows
venv\Scripts\activate
Your terminal prompt should now show (venv) — this means pip installs will go into
venv/lib/.../site-packages , not globally.
Step 4 — Install FastAPI + a server (uvicorn)
pip install fastapi "uvicorn[standard]"
Yes — FastAPI supports installing any module from pip. It’s a normal Python package;
you use pip for FastAPI itself and for any extra library you need (database drivers, auth,
etc.), exactly like installing any other pip package.
Step 5 — Save your dependencies (like [Link] )
pip freeze > [Link]
Anyone can then run pip install -r [Link] to install the same packages —
this is Python’s equivalent of [Link] + npm install .
2. Your First FastAPI App
Create [Link] :
from fastapi import FastAPI
app = FastAPI()
@[Link]("/")
def read_root():
return {"message": "Hello, FastAPI!"}
Run the server:
uvicorn main:app --reload
main = filename ( [Link] )
app = the FastAPI instance variable
--reload = auto-restart on code changes (like nodemon )
Now visit:
[Link] → your JSON response
[Link] → free interactive API docs (Swagger UI) — huge
FastAPI perk
3. Path Params & Query Params
from fastapi import FastAPI
app = FastAPI()
# Path parameter (part of the URL)
@[Link]("/items/{item_id}")
def get_item(item_id: int):
return {"item_id": item_id}
# Query parameter (?key=value)
@[Link]("/search")
def search_items(q: str = None, limit: int = 10):
return {"query": q, "limit": limit}
/items/5 → path param item_id = 5
/search?q=phone&limit=5 → query params q="phone", limit=5
FastAPI automatically validates types — visit /items/abc and it’ll return a clean error since
item_id must be an int .
4. Full CRUD Example (in-memory, no database yet)
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
# Pydantic model = defines the shape/validation of request/response data
class Item(BaseModel):
name: str
price: float
in_stock: bool = True
# Fake "database" (just a dict)
db = {}
next_id = 1
# CREATE
@[Link]("/items")
def create_item(item: Item):
global next_id
db[next_id] = item
next_id += 1
return {"id": next_id - 1, **[Link]()}
# READ (all)
@[Link]("/items")
def get_items():
return db
# READ (one)
@[Link]("/items/{item_id}")
def get_item(item_id: int):
if item_id not in db:
raise HTTPException(status_code=404, detail="Item not found")
return db[item_id]
# UPDATE
@[Link]("/items/{item_id}")
def update_item(item_id: int, item: Item):
if item_id not in db:
raise HTTPException(status_code=404, detail="Item not found")
db[item_id] = item
return {"id": item_id, **[Link]()}
# DELETE
@[Link]("/items/{item_id}")
def delete_item(item_id: int):
if item_id not in db:
raise HTTPException(status_code=404, detail="Item not found")
del db[item_id]
return {"message": "Item deleted"}
Test it all via /docs in your browser — you can send POST/PUT/DELETE requests right from
the Swagger UI without needing Postman.
5. Connecting FastAPI to PostgreSQL
Step 1 — Install what you need
pip install sqlalchemy psycopg2-binary
( psycopg2-binary = PostgreSQL driver, sqlalchemy = ORM, like an equivalent of
Sequelize/Prisma in Node)
Step 2 — [Link]
from sqlalchemy import create_engine
from [Link] import declarative_base
from [Link] import sessionmaker
DATABASE_URL = "postgresql://username:password@localhost:5432/mydatabase"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
Step 3 — [Link]
from sqlalchemy import Column, Integer, String, Float, Boolean
from database import Base
class ItemModel(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
price = Column(Float)
in_stock = Column(Boolean, default=True)
Step 4 — [Link] (CRUD wired to PostgreSQL)
from fastapi import FastAPI, HTTPException, Depends
from [Link] import Session
from pydantic import BaseModel
from database import engine, SessionLocal, Base
from models import ItemModel
[Link].create_all(bind=engine) # creates tables if they don't exist
app = FastAPI()
# Dependency: gives each request its own DB session
def get_db():
db = SessionLocal()
try:
yield db
finally:
[Link]()
class Item(BaseModel):
name: str
price: float
in_stock: bool = True
# CREATE
@[Link]("/items")
def create_item(item: Item, db: Session = Depends(get_db)):
db_item = ItemModel(**[Link]())
[Link](db_item)
[Link]()
[Link](db_item)
return db_item
# READ (all)
@[Link]("/items")
def get_items(db: Session = Depends(get_db)):
return [Link](ItemModel).all()
# READ (one)
@[Link]("/items/{item_id}")
def get_item(item_id: int, db: Session = Depends(get_db)):
item = [Link](ItemModel).filter([Link] == item_id).first()
if not item:
raise HTTPException(status_code=404, detail="Item not found")
return item
# UPDATE
@[Link]("/items/{item_id}")
def update_item(item_id: int, item: Item, db: Session = Depends(get_db)):
db_item = [Link](ItemModel).filter([Link] == item_id).first()
if not db_item:
raise HTTPException(status_code=404, detail="Item not found")
for key, value in [Link]().items():
setattr(db_item, key, value)
[Link]()
[Link](db_item)
return db_item
# DELETE
@[Link]("/items/{item_id}")
def delete_item(item_id: int, db: Session = Depends(get_db)):
db_item = [Link](ItemModel).filter([Link] == item_id).first()
if not db_item:
raise HTTPException(status_code=404, detail="Item not found")
[Link](db_item)
[Link]()
return {"message": "Item deleted"}
Step 5 — Update the connection string
Replace in [Link] :
DATABASE_URL = "postgresql://username:password@localhost:5432/mydatabase"
with your real PostgreSQL username, password, host, port, and database name.
Run it the same way:
uvicorn main:app --reload
6. Recommended Project Structure
fastapi-demo/
├── venv/ # virtual environment (not committed to git)
├── [Link] # FastAPI app + routes
├── [Link] # DB connection setup
├── [Link] # SQLAlchemy models (tables)
├── [Link] # dependency list (like [Link])
7. Quick Reference Cheat Sheet
Task [Link] equivalent FastAPI
Install package npm install express pip install fastapi
Package storage ./node_modules/ venv/lib/.../site-packages/
Dependency list [Link] [Link]
Run server node [Link] uvicorn main:app --reload
ORM Sequelize/Prisma SQLAlchemy
Auto docs manual (Swagger setup) built-in at /docs
That covers install → CRUD → params → PostgreSQL. If you want, I can also add JWT
authentication or Docker setup as a next step.