Creating a Complete RESTful API with FastAPI
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.