Skip to main content

Python FastAPI Basics

Introduction

FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.7+ based on standard Python type hints. It was created by Sebastián Ramírez and has quickly gained popularity among Python developers due to its simplicity, speed, and developer-friendly features.

FastAPI stands out from other Python web frameworks because of:

  • Speed: It's one of the fastest Python frameworks available, on par with NodeJS and Go
  • Easy to use: Designed to be easy to use and learn
  • Less code: Minimizes code duplication, reducing bugs
  • Automatic documentation: Generates interactive API documentation automatically
  • Modern Python: Takes full advantage of Python 3.7+ features like type hints

In this tutorial, we'll cover the basics of FastAPI and build a simple API to understand how it works.

Prerequisites

Before we begin, make sure you have:

  • Python 3.7 or later installed
  • Basic understanding of Python
  • Familiarity with API concepts
  • A code editor of your choice

Installation

Let's start by installing FastAPI and Uvicorn, an ASGI server that we'll use to run our FastAPI application:

bash
pip install fastapi uvicorn

Creating Your First FastAPI Application

Let's create a simple "Hello World" API:

python
from fastapi import FastAPI

# Create a FastAPI instance
app = FastAPI()

# Define a route
@app.get("/")
def read_root():
return {"message": "Hello, FastAPI!"}

Save this code as main.py. To run the application, use the following command:

bash
uvicorn main:app --reload

Breaking down this command:

  • main: The name of the Python file (main.py)
  • app: The FastAPI instance name inside the file
  • --reload: Enables auto-reload when code changes

Now, open your browser and navigate to http://127.0.0.1:8000. You should see:

json
{
"message": "Hello, FastAPI!"
}

Congratulations! You've created your first FastAPI application.

Path Parameters

Let's make our API more dynamic by adding path parameters:

python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
return {"message": "Hello, FastAPI!"}

@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}

Notice how we declared item_id as an int. FastAPI will:

  1. Convert the path parameter to the specified type
  2. Validate the data
  3. Document the parameter in the API docs

Try accessing http://127.0.0.1:8000/items/5 and you'll see:

json
{
"item_id": 5
}

If you try with a non-integer value like http://127.0.0.1:8000/items/abc, FastAPI will return an error, as it expects an integer.

Query Parameters

Query parameters are specified after the ? in a URL. FastAPI makes it easy to work with them:

python
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/")
def read_items(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}

If you access http://127.0.0.1:8000/items/?skip=20&limit=50, you'll see:

json
{
"skip": 20,
"limit": 50
}

Parameters with default values are optional. If you simply access http://127.0.0.1:8000/items/, you'll get:

json
{
"skip": 0,
"limit": 10
}

Request Body

When you need to send data to the API, you can use a request body. FastAPI makes it easy to define request bodies using Pydantic models:

python
from fastapi import FastAPI
from pydantic import BaseModel

class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None

app = FastAPI()

@app.post("/items/")
def create_item(item: Item):
item_dict = item.dict()
if item.tax:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
return item_dict

To test this endpoint, you can use tools like Postman, curl, or the automatically generated interactive documentation.

Automatic Documentation

One of the most powerful features of FastAPI is its automatic documentation. FastAPI automatically generates interactive API documentation based on your code.

To access the documentation, run your FastAPI application and navigate to:

  • Swagger UI: http://127.0.0.1:8000/docs
  • ReDoc: http://127.0.0.1:8000/redoc

These interfaces allow you to view your API endpoints, send requests directly from the browser, and see the expected request/response formats.

Building a Complete REST API

Now, let's put everything together to build a simple REST API for managing a collection of books:

python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional

app = FastAPI(title="Book Library API")

# Pydantic model for a book
class Book(BaseModel):
id: Optional[int] = None
title: str
author: str
pages: int
published: bool = False

# In-memory database (for demonstration)
books_db = []
book_id_counter = 1

@app.post("/books/", response_model=Book, status_code=201)
def create_book(book: Book):
global book_id_counter
book.id = book_id_counter
book_id_counter += 1
books_db.append(book)
return book

@app.get("/books/", response_model=List[Book])
def read_books(skip: int = 0, limit: int = 10):
return books_db[skip: skip + limit]

@app.get("/books/{book_id}", response_model=Book)
def read_book(book_id: int):
for book in books_db:
if book.id == book_id:
return book
raise HTTPException(status_code=404, detail="Book not found")

@app.put("/books/{book_id}", response_model=Book)
def update_book(book_id: int, updated_book: Book):
for i, book in enumerate(books_db):
if book.id == book_id:
updated_book.id = book_id
books_db[i] = updated_book
return updated_book
raise HTTPException(status_code=404, detail="Book not found")

@app.delete("/books/{book_id}", status_code=204)
def delete_book(book_id: int):
for i, book in enumerate(books_db):
if book.id == book_id:
books_db.pop(i)
return
raise HTTPException(status_code=404, detail="Book not found")

This API allows you to:

  • Create a new book
  • Retrieve all books (with pagination)
  • Retrieve a specific book by ID
  • Update a book
  • Delete a book

Exception Handling

In the example above, we used HTTPException to handle errors. FastAPI provides a simple way to manage exceptions:

python
from fastapi import FastAPI, HTTPException

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int):
if item_id == 0:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}

Adding Dependency Injection

FastAPI has a powerful dependency injection system that helps you create reusable components:

python
from fastapi import FastAPI, Depends, HTTPException

app = FastAPI()

def get_db():
db = {"key": "value"}
return db

@app.get("/items/")
def read_items(db: dict = Depends(get_db)):
return {"db": db}

When a request is made to /items/, FastAPI will:

  1. Call the get_db() function
  2. Pass the result to read_items() as db

This is extremely useful for database connections, authentication, and other common tasks.

Summary

In this tutorial, we've covered the basics of FastAPI, including:

  • Setting up a FastAPI application
  • Creating API endpoints with path and query parameters
  • Working with request bodies using Pydantic models
  • Automatic API documentation
  • Building a complete REST API
  • Exception handling
  • Introduction to dependency injection

FastAPI provides a modern, efficient way to build APIs with Python. Its focus on developer experience, combined with its performance and automatic documentation, makes it an excellent choice for Python web development.

Additional Resources

Here are some resources to dive deeper into FastAPI:

  1. Official FastAPI documentation
  2. FastAPI GitHub repository
  3. Pydantic documentation

Practice Exercises

  1. Extend the book API to include features like searching by title or author
  2. Add a rating system to the books API
  3. Implement basic authentication for the API
  4. Create a front-end application that interacts with your FastAPI backend
  5. Add database integration using SQLAlchemy instead of the in-memory list

By completing these exercises, you'll gain a deeper understanding of FastAPI and be well on your way to building robust web applications with Python.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)