Building Your First REST API with FastAPI: A Practical Guide
Source: Dev.to
Why FastAPI?
FastAPI stands out for several reasons:
- Performance: One of the fastest Python frameworks available, comparable to Node.js and Go.
- Type Safety: Built on Python type hints for better code quality and editor support.
- Auto Documentation: Swagger UI and ReDoc documentation generated automatically.
- Modern Python: Uses
async/awaitfor handling concurrent requests efficiently.
Setting Up
First, install FastAPI and uvicorn (an ASGI server):
pip install fastapi uvicorn
Creating a Simple API
Here’s a basic FastAPI application that manages a list of tasks:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
app = FastAPI()
# Pydantic model for data validation
class Task(BaseModel):
id: int
title: str
description: Optional[str] = None
completed: bool = False
# In-memory storage
tasks_db: List[Task] = []
@app.get("/")
def read_root():
return {"message": "Welcome to the Task API"}
@app.get("/tasks", response_model=List[Task])
def get_tasks():
return tasks_db
@app.get("/tasks/{task_id}", response_model=Task)
def get_task(task_id: int):
task = next((t for t in tasks_db if t.id == task_id), None)
if not task:
raise HTTPException(status_code=404, detail="Task not found")
return task
@app.post("/tasks", response_model=Task, status_code=201)
def create_task(task: Task):
tasks_db.append(task)
return task
@app.put("/tasks/{task_id}", response_model=Task)
def update_task(task_id: int, updated_task: Task):
for index, task in enumerate(tasks_db):
if task.id == task_id:
tasks_db[index] = updated_task
return updated_task
raise HTTPException(status_code=404, detail="Task not found")
@app.delete("/tasks/{task_id}")
def delete_task(task_id: int):
for index, task in enumerate(tasks_db):
if task.id == task_id:
tasks_db.pop(index)
return {"message": "Task deleted successfully"}
raise HTTPException(status_code=404, detail="Task not found")
Running Your API
Start the development server:
uvicorn main:app --reload
Your API is now running at http://localhost:8000.
Automatic Documentation
FastAPI provides interactive documentation out of the box:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc
You can test all your endpoints directly from the browser.
Key Features Demonstrated
- Pydantic Models: The
Taskclass uses Pydantic for automatic data validation. Invalid data triggers clear error responses. - Type Hints: Python type hints throughout the code enable better IDE support and early error detection.
- Path Parameters: The
{task_id}syntax in routes automatically extracts and validates URL parameters. - HTTP Status Codes: Proper status codes (e.g.,
201for creation) follow REST best practices. - Exception Handling:
HTTPExceptionprovides clean error responses with appropriate status codes.
Adding Async Support
FastAPI shines with async operations. Below is an example with a simulated asynchronous database call:
import asyncio
from fastapi import HTTPException
@app.get("/tasks/async/{task_id}")
async def get_task_async(task_id: int):
# Simulate async database call
await asyncio.sleep(0.1)
task = next((t for t in tasks_db if t.id == task_id), None)
if not task:
raise HTTPException(status_code=404, detail="Task not found")
return task
Next Steps
To build production‑ready APIs, consider:
- Connecting to a real database (PostgreSQL, MongoDB)
- Adding authentication and authorization
- Implementing comprehensive request validation and error handling
- Setting up CORS for frontend integration
- Writing tests using pytest
- Containerizing with Docker
Conclusion
FastAPI makes building APIs in Python straightforward and enjoyable. Automatic validation, documentation, and modern Python features reduce boilerplate and let you focus on business logic. Its performance and developer experience make it an excellent choice for both small projects and large‑scale applications.