Building Your First FastAPI Server: A Comprehensive Guide
FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.7+ based on standard Python type hints. In this comprehensive guide, we’ll walk through creating a FastAPI project from scratch, covering everything from setup to building your first endpoints.
Prerequisites
Before we begin, make sure you have:
- Python 3.7 or higher installed
- Basic knowledge of Python
- A code editor (VS Code, PyCharm, etc.)
- Terminal/Command Prompt access
Setting Up Your Project
Let’s start by creating a new project directory and setting up a virtual environment:
# Create project directory
mkdir fastapi-tutorial
cd fastapi-tutorial
# Create and activate virtual environment
python -m venv venv
source venv/bin/activate # On Windows, use: venv\Scripts\activate
# Install required packages
pip install fastapi uvicorn
Create a requirements.txt
file to track dependencies:
pip freeze > requirements.txt
Creating Your First FastAPI Application
Create a new file called main.py
in your project directory:
from fastapi import FastAPI
from typing import Optional
# Initialize FastAPI application
app = FastAPI(
title="My First FastAPI App",
description="A simple FastAPI application to demonstrate basic concepts",
version="1.0.0"
)
# Root endpoint
@app.get("/")
async def read_root():
return {"message": "Welcome to FastAPI!"}
# Path parameter example
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
# Query parameter example
@app.get("/search/")
async def search_items(q: str, skip: int = 0, limit: Optional[int] = 10):
return {
"query": q,
"skip": skip,
"limit": limit
}
Running Your Application
To run your FastAPI application:
uvicorn main:app --reload
Your API will be available at http://127.0.0.1:8000
.
Understanding Key Concepts
1. Path Operations (Routes)
FastAPI uses path operations decorators to define API endpoints. The most common HTTP methods are:
@app.get("/") # Read operations
@app.post("/") # Create operations
@app.put("/") # Update operations
@app.delete("/") # Delete operations
2. Request Body
Let’s add an endpoint that accepts a request body:
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
@app.post("/items/")
async def create_item(item: Item):
return item
3. Query Parameters
Query parameters are automatically parsed from the URL:
@app.get("/products/")
async def get_products(
category: str,
min_price: Optional[float] = None,
max_price: Optional[float] = None
):
return {
"category": category,
"price_range": {
"min": min_price,
"max": max_price
}
}
4. Path Parameters
Path parameters are part of the URL path:
@app.get("/users/{user_id}/posts/{post_id}")
async def get_user_post(user_id: int, post_id: int):
return {
"user_id": user_id,
"post_id": post_id
}
Advanced Features
1. Response Models
Response models help validate and limit the output data:
from pydantic import BaseModel
class UserBase(BaseModel):
username: str
email: str
full_name: Optional[str] = None
class UserResponse(UserBase):
id: int
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
# Simulated user data
return {
"id": user_id,
"username": "johndoe",
"email": "john@example.com",
"full_name": "John Doe"
}
2. Dependencies
FastAPI’s dependency injection system is powerful for code reuse:
from fastapi import Depends, HTTPException
async def verify_token(token: str):
if token != "secret-token":
raise HTTPException(status_code=401, detail="Invalid token")
return token
@app.get("/secure-endpoint/")
async def secure_operation(token: str = Depends(verify_token)):
return {"message": "Access granted!"}
3. Error Handling
Handle exceptions gracefully:
from fastapi import HTTPException
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id < 0:
raise HTTPException(
status_code=400,
detail="Item ID cannot be negative"
)
return {"item_id": item_id}
Automatic Documentation
One of FastAPI’s best features is automatic API documentation. Visit:
/docs
for the Swagger UI documentation/redoc
for the ReDoc documentation
These endpoints provide interactive documentation for your API, automatically generated from your code and docstrings.
Project Structure
For larger applications, consider organizing your code like this:
fastapi-tutorial/
│
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── dependencies.py
│ ├── routers/
│ │ ├── __init__.py
│ │ ├── users.py
│ │ └── items.py
│ └── models/
│ ├── __init__.py
│ └── user.py
│
├── tests/
│ ├── __init__.py
│ ├── test_main.py
│ └── test_users.py
│
├── requirements.txt
└── README.md
Testing Your FastAPI Application
FastAPI makes testing easy with TestClient:
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Welcome to FastAPI!"}
def test_read_item():
response = client.get("/items/1")
assert response.status_code == 200
assert response.json() == {"item_id": 1}
Conclusion
FastAPI is an excellent choice for building modern APIs with Python. It offers:
- High performance
- Easy to learn and use
- Automatic API documentation
- Modern Python features
- Type checking
- Dependency injection
This guide covered the basics of FastAPI, but there’s much more to explore. The official documentation is an excellent resource for learning advanced features like:
- WebSocket support
- File uploads
- Background tasks
- Security and authentication
- Database integration
Start building your API with FastAPI, and you’ll quickly appreciate its power and simplicity!
Remember to check out the complete source code for this tutorial on my GitHub repository, and feel free to reach out if you have any questions!