FastAPI Path Operation Decorators
Introduction
In FastAPI, path operation decorators are a crucial feature that allows you to define API endpoints with specific HTTP methods. These decorators connect your Python functions to specific URL paths, creating what are called "path operations" in FastAPI terminology.
A path operation is a combination of:
- A specific HTTP method (GET, POST, PUT, DELETE, etc.)
- A specific URL path (like
/items/
,/users/{user_id}
) - A function that will handle requests to that path with that method
Path operation decorators make your API code expressive, easy to read, and well-organized.
Basic Path Operation Decorators
FastAPI provides decorators for all standard HTTP methods. Let's look at the most common ones:
GET Requests
The @app.get()
decorator is used for retrieving data without changing the server state.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
When you visit the root URL /
in a browser, you'll see:
{
"message": "Hello World"
}
POST Requests
The @app.post()
decorator is used for creating new data:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.post("/items/")
def create_item(item: Item):
return {"item_name": item.name, "item_price": item.price, "message": "Item created"}
Sending a POST request with the following JSON body:
{
"name": "Laptop",
"price": 999.99
}
Will result in:
{
"item_name": "Laptop",
"item_price": 999.99,
"message": "Item created"
}
PUT Requests
Use @app.put()
for updating existing resources:
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_id": item_id, "item_name": item.name, "item_price": item.price}
DELETE Requests
Use @app.delete()
for removing resources:
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
return {"item_id": item_id, "message": "Item deleted"}
Advanced Path Operation Decorators
FastAPI allows you to customize how path operations work beyond just specifying the HTTP method and path.
Status Codes
You can specify the response status code:
from fastapi import FastAPI, status
app = FastAPI()
@app.post("/items/", status_code=status.HTTP_201_CREATED)
def create_item(name: str):
return {"name": name}
This example will return HTTP status code 201 (Created) instead of the default 200 (OK).
Response Model
You can define the exact structure of your response:
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List
app = FastAPI()
class Item(BaseModel):
name: str
price: float
class ItemResponse(BaseModel):
id: int
name: str
price: float
@app.post("/items/", response_model=ItemResponse)
def create_item(item: Item):
# In a real app, we'd save to a database here
return {"id": 1, "name": item.name, "price": item.price}
This ensures that the response will match the ItemResponse
model and automatically generates proper API documentation.
Multiple Path Parameters
You can use multiple parameters in your paths:
@app.get("/users/{user_id}/items/{item_id}")
def get_user_item(user_id: int, item_id: int):
return {"user_id": user_id, "item_id": item_id}
For example, /users/1/items/42
would return:
{
"user_id": 1,
"item_id": 42
}
Tags and Documentation
You can organize your API endpoints with tags:
@app.get("/users/", tags=["users"])
def get_users():
return [{"name": "Harry"}, {"name": "Ron"}]
@app.get("/items/", tags=["items"])
def get_items():
return [{"name": "Wand"}, {"name": "Broomstick"}]
These tags will group your endpoints in the automatically generated documentation.
Real-World Example: Building a Simple To-Do API
Let's build a simple to-do API using different path operation decorators:
from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel
from typing import List, Optional
app = FastAPI()
# Our data model
class Todo(BaseModel):
title: str
description: Optional[str] = None
completed: bool = False
# In-memory database
todos = {}
todo_id_counter = 1
# Create a new todo
@app.post("/todos/", status_code=status.HTTP_201_CREATED, response_model=Todo)
def create_todo(todo: Todo):
global todo_id_counter
todos[todo_id_counter] = todo
new_todo = todo.dict()
new_todo["id"] = todo_id_counter
todo_id_counter += 1
return new_todo
# Get all todos
@app.get("/todos/", response_model=List[dict])
def get_todos():
result = []
for id, todo in todos.items():
todo_dict = todo.dict()
todo_dict["id"] = id
result.append(todo_dict)
return result
# Get a specific todo
@app.get("/todos/{todo_id}", response_model=dict)
def get_todo(todo_id: int):
if todo_id not in todos:
raise HTTPException(status_code=404, detail="Todo not found")
todo_dict = todos[todo_id].dict()
todo_dict["id"] = todo_id
return todo_dict
# Update a todo
@app.put("/todos/{todo_id}", response_model=dict)
def update_todo(todo_id: int, todo: Todo):
if todo_id not in todos:
raise HTTPException(status_code=404, detail="Todo not found")
todos[todo_id] = todo
todo_dict = todo.dict()
todo_dict["id"] = todo_id
return todo_dict
# Delete a todo
@app.delete("/todos/{todo_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_todo(todo_id: int):
if todo_id not in todos:
raise HTTPException(status_code=404, detail="Todo not found")
del todos[todo_id]
return None
This example demonstrates how different HTTP methods can be used to create a RESTful API for managing todos.
Path Operation Decorator Parameters
FastAPI's path operation decorators support several parameters:
Parameter | Description | Example |
---|---|---|
response_model | Defines the model used for the response | @app.get("/items/", response_model=List[Item]) |
status_code | Sets the HTTP status code for the response | @app.post("/items/", status_code=201) |
tags | Groups operations in the documentation | @app.get("/items/", tags=["items"]) |
summary | Provides a summary for the documentation | @app.get("/items/", summary="Get all items") |
description | Adds a detailed description | @app.get("/items/", description="Get all items from the database") |
response_description | Describes the response | @app.get("/items/", response_description="List of items") |
deprecated | Marks an operation as deprecated | @app.get("/items/", deprecated=True) |
Summary
Path operation decorators in FastAPI are a powerful way to define your API endpoints. They allow you to:
- Connect URL paths with specific HTTP methods and Python functions
- Specify response models and status codes
- Add metadata for API documentation
- Create clear, organized, and maintainable API code
By using the appropriate decorators (@app.get()
, @app.post()
, @app.put()
, @app.delete()
, etc.), you can build RESTful APIs that follow best practices and are well-documented automatically.
Additional Resources
Exercises
- Create a simple API with endpoints for managing a library of books using all CRUD operations (Create, Read, Update, Delete).
- Implement an API endpoint that returns different status codes based on certain conditions.
- Build an API with endpoints grouped by tags for better documentation organization.
- Create an endpoint with a custom response model that transforms the data before returning it to the client.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)