Creating a Complete RESTful API with FastAPI

Joël-Steve N.
3 min readJul 5, 2024

--

Develop a Full CRUD Application

FastAPI is a modern web framework for building APIs with Python 3.7+ based on standard Python type hints. It is fast, easy to use, and highly suitable for building RESTful APIs. In this article, we will walk through creating a complete RESTful API for a CRUD application using FastAPI.

Project Structure

Let’s start by defining the project structure for our CRUD application:

fastapi_crud/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── models.py
│ ├── schemas.py
│ ├── crud.py
│ └── database.py
├── requirements.txt
└── README.md

1. Setting Up Your Environment

First, create a virtual environment and install FastAPI and an ASGI server, Uvicorn:

python -m venv venv
source venv/bin/activate # On Windows use `venv\Scripts\activate`
pip install fastapi uvicorn sqlalchemy databases

Requirement file (requirements.txt) :

annotated-types==0.7.0
anyio==4.4.0
certifi==2024.7.4
click==8.1.7
colorama==0.4.6
databases==0.9.0
dnspython==2.6.1
email_validator==2.2.0
fastapi==0.111.0
fastapi-cli==0.0.4
greenlet==3.0.3
h11==0.14.0
httpcore==1.0.5
httptools==0.6.1
httpx==0.27.0
idna==3.7
Jinja2==3.1.4
markdown-it-py==3.0.0
MarkupSafe==2.1.5
mdurl==0.1.2
orjson==3.10.6
pydantic==2.8.2
pydantic_core==2.20.1
Pygments==2.18.0
python-dotenv==1.0.1
python-multipart==0.0.9
PyYAML==6.0.1
rich==13.7.1
shellingham==1.5.4
sniffio==1.3.1
SQLAlchemy==2.0.31
starlette==0.37.2
typer==0.12.3
typing_extensions==4.12.2
ujson==5.10.0
uvicorn==0.30.1
watchfiles==0.22.0
websockets==12.0

2. Defining the Database Models

We’ll use SQLAlchemy to define our database models. Create the models.py file in the app directory.

Example: models.py

from sqlalchemy import Column, Integer, String
from .database import Base


class Item(Base):
__tablename__ = "items"

id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
description = Column(String, index=True)

3. Creating the Pydantic Schemas

Next, define the Pydantic schemas in schemas.py to ensure data validation.

Example: schemas.py

from pydantic import BaseModel

class ItemBase(BaseModel):
title: str
description: str

class ItemCreate(ItemBase):
pass

class Item(ItemBase):
id: int

class Config:
orm_mode = True

4. CRUD Operations

Now, implement the CRUD operations in crud.py.

Example: crud.py

from sqlalchemy.orm import Session
from . import models, schemas

def get_item(db: Session, item_id: int):
return db.query(models.Item).filter(models.Item.id == item_id).first()

def get_items(db: Session, skip: int = 0, limit: int = 10):
return db.query(models.Item).offset(skip).limit(limit).all()

def create_item(db: Session, item: schemas.ItemCreate):
db_item = models.Item(title=item.title, description=item.description)
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item

def delete_item(db: Session, item_id: int):
db_item = db.query(models.Item).filter(models.Item.id == item_id).first()
if db_item:
db.delete(db_item)
db.commit()
return db_item

5. Database Configuration

Set up the database configuration in database.py.

Example: database.py

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

DATABASE_URL = "sqlite:///./test.db"

engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

def init_db():
Base.metadata.create_all(bind=engine)

# Dependency to get the database session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

6. FastAPI Application

Finally, create the FastAPI application in main.py.

Example: main.py

from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from . import schemas, crud
from .database import get_db

app = FastAPI(
title="RESTful API",
description="Creating a Complete RESTful API with FastAPI: Develop a Full CRUD Application",
version="0.0.1"
)

@app.post("/items/", response_model=schemas.Item)
def create_item(item: schemas.ItemCreate, db: Session = Depends(get_db)):
return crud.create_item(db=db, item=item)

@app.get("/items/", response_model=list[schemas.Item])
def read_items(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
items = crud.get_items(db, skip=skip, limit=limit)
return items

@app.get("/items/{item_id}", response_model=schemas.Item)
def read_item(item_id: int, db: Session = Depends(get_db)):
db_item = crud.get_item(db, item_id=item_id)
if db_item is None:
raise HTTPException(status_code=404, detail="Item not found")
return db_item

@app.delete("/items/{item_id}", response_model=schemas.Item)
def delete_item(item_id: int, db: Session = Depends(get_db)):
db_item = crud.get_item(db, item_id=item_id)
if db_item is None:
raise HTTPException(status_code=404, detail="Item not found")
return crud.delete_item(db, item_id=item_id)

7. Running the Application

To run the application, use the following command:

uvicorn app.main:app --reload

Navigate to http://127.0.0.1:8000 in your browser to see your FastAPI application in action. You can also visit http://127.0.0.1:8000/docs for the automatically generated Swagger documentation.

Conclusion

In this article, we’ve walked through creating a complete RESTful API with FastAPI, including setting up the project structure, defining database models, creating Pydantic schemas for data validation, implementing CRUD operations, and configuring the database. FastAPI’s ease of use and automatic documentation make it an excellent choice for developing APIs.

--

--

Joël-Steve N.
Joël-Steve N.

Written by Joël-Steve N.

Senior Back-End Developer (Python, JavaScript, Java) | Community Manager & Tech Leader

Responses (1)