FastAPI: An Introduction

What is FastAPI?

FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.6+ based on standard Python type hints. It leverages Python's asyncio capabilities, allowing for high throughput in handling requests. FastAPI is designed to be easy to use and to help developers build robust APIs quickly and efficiently.

Why Use FastAPI?

  • High Performance: Comparable to NodeJS and Go.

  • Easy to Learn: Intuitive design with automatic interactive documentation.

  • Type Safety: Utilizes Python type hints for data validation and serialization.

  • Automatic Documentation: Generates OpenAPI and Swagger UI docs automatically.

  • Asynchronous Support: Built-in support for asynchronous programming.


Key Features of FastAPI

  • Declarative Routing: Use Python decorators to define routes.

  • Data Validation: Automatic validation based on type hints using Pydantic.

  • Interactive API Docs: Automatically generated Swagger UI and ReDoc.

  • Dependency Injection: Simplify the design of scalable applications.

  • Asynchronous Capabilities: Support for async and await for non-blocking code.


Setting Up FastAPI

Prerequisites

  • Python 3.6+

  • pip (Python package manager)

Installation

pip install fastapi uvicorn
  • fastapi: The web framework.

  • uvicorn: An ASGI server to run the FastAPI app.


Creating a Basic API with FastAPI

We will create a simple API that performs basic CRUD (Create, Read, Update, Delete) operations on an in-memory list of items.

Step-by-Step Guide

1. Project Structure

Create a new directory for your project:

mkdir fastapi-demo
cd fastapi-demo

Create a file named main.py:

touch main.py

2. Import Necessary Libraries

# main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, List

3. Initialize the FastAPI App

app = FastAPI()

4. Define the Data Model

Use Pydantic's BaseModel to define a schema for items.

class Item(BaseModel):
    id: int
    name: str
    description: Optional[str] = None
    price: float
    on_offer: Optional[bool] = None

5. Create an In-Memory Data Store

items = [
    Item(id=1, name="Item One", description="First item", price=10.0, on_offer=False),
    Item(id=2, name="Item Two", description="Second item", price=20.0, on_offer=True),
]

6. Define CRUD Endpoints

GET Endpoint: Retrieve All Items

@app.get("/items", response_model=List[Item])
def get_items():
    return items

GET Endpoint: Retrieve a Single Item by ID

@app.get("/items/{item_id}", response_model=Item)
def get_item(item_id: int):
    for item in items:
        if item.id == item_id:
            return item
    raise HTTPException(status_code=404, detail="Item not found")

POST Endpoint: Create a New Item

@app.post("/items", response_model=Item)
def create_item(item: Item):
    items.append(item)
    return item

PUT Endpoint: Update an Existing Item

@app.put("/items/{item_id}", response_model=Item)
def update_item(item_id: int, updated_item: Item):
    for index, item in enumerate(items):
        if item.id == item_id:
            items[index] = updated_item
            return updated_item
    raise HTTPException(status_code=404, detail="Item not found")

DELETE Endpoint: Delete an Item

@app.delete("/items/{item_id}")
def delete_item(item_id: int):
    for index, item in enumerate(items):
        if item.id == item_id:
            del items[index]
            return {"message": "Item deleted successfully"}
    raise HTTPException(status_code=404, detail="Item not found")

7. Running the FastAPI Application

Run the app using Uvicorn:

uvicorn main:app --reload
  • main: Refers to the main.py file.

  • app: The FastAPI instance in main.py.

  • --reload: Enables auto-reload on code changes.


End-to-End Functionality of FastAPI

Testing the API Endpoints

You can test the API using Swagger UI or cURL/Postman.

1. Accessing Interactive Documentation

Navigate to http://127.0.0.1:8000/docs to access the Swagger UI.

2. Performing CRUD Operations

GET All Items

  • Endpoint: GET /items

  • Description: Retrieves a list of all items.

Example Response:

[
  {
    "id": 1,
    "name": "Item One",
    "description": "First item",
    "price": 10.0,
    "on_offer": false
  },
  {
    "id": 2,
    "name": "Item Two",
    "description": "Second item",
    "price": 20.0,
    "on_offer": true
  }
]

GET Single Item

  • Endpoint: GET /items/{item_id}

  • Example: GET /items/1

Example Response:

{
  "id": 1,
  "name": "Item One",
  "description": "First item",
  "price": 10.0,
  "on_offer": false
}

POST Create a New Item

  • Endpoint: POST /items

  • Request Body:

{
  "id": 3,
  "name": "Item Three",
  "description": "Third item",
  "price": 30.0,
  "on_offer": false
}

Example Response:

{
  "id": 3,
  "name": "Item Three",
  "description": "Third item",
  "price": 30.0,
  "on_offer": false
}

PUT Update an Existing Item

  • Endpoint: PUT /items/{item_id}

  • Example: PUT /items/2

  • Request Body:

{
  "id": 2,
  "name": "Updated Item Two",
  "description": "Updated second item",
  "price": 25.0,
  "on_offer": true
}

Example Response:

{
  "id": 2,
  "name": "Updated Item Two",
  "description": "Updated second item",
  "price": 25.0,
  "on_offer": true
}

DELETE Remove an Item

  • Endpoint: DELETE /items/{item_id}

  • Example: DELETE /items/1

Example Response:

{
  "message": "Item deleted successfully"
}

3. Understanding the Code

Data Model with Pydantic

  • Validation: Pydantic models ensure the data conforms to the specified types.

  • Optional Fields: Fields with Optional or default values are not mandatory.

Endpoints and Path Parameters

  • Path Parameters: Defined using curly braces {} in route paths.

  • Query Parameters: Additional parameters in the URL after ?, not used in this basic example.

Response Models

  • The response_model parameter ensures the response data matches the specified Pydantic model.

Exception Handling

  • HTTPException: Used to return HTTP errors with custom status codes and messages.

4. Running and Testing the Application

Starting the Server

uvicorn main:app --reload

Available Routes

  • GET /items

  • GET /items/{item_id}

  • POST /items

  • PUT /items/{item_id}

  • DELETE /items/{item_id}

Using Swagger UI

Using cURL for Testing

GET All Items

curl -X GET "http://127.0.0.1:8000/items" -H "accept: application/json"

POST Create an Item

curl -X POST "http://127.0.0.1:8000/items" -H "Content-Type: application/json" -d '{
  "id": 4,
  "name": "Item Four",
  "description": "Fourth item",
  "price": 40.0,
  "on_offer": false
}'

PUT Update an Item

curl -X PUT "http://127.0.0.1:8000/items/2" -H "Content-Type: application/json" -d '{
  "id": 2,
  "name": "Updated Item Two",
  "description": "Updated second item",
  "price": 22.0,
  "on_offer": true
}'

DELETE Remove an Item

curl -X DELETE "http://127.0.0.1:8000/items/3"

FastAPI Commands Explained

Installation Commands

  • Install FastAPI and Uvicorn

      pip install fastapi uvicorn
    

Running the Application

  • Start the Server

      uvicorn main:app --reload
    
    • main: Name of the Python file (main.py).

    • app: The FastAPI instance.

    • --reload: Enables automatic reload on code changes.

Alternative Uvicorn Options

  • Specify Host and Port

      uvicorn main:app --host 0.0.0.0 --port 8000
    
  • Run in the Background

      uvicorn main:app --reload &
    
  • Run with Gunicorn (for Production)

      pip install gunicorn
      pip install uvicorn[standard]
      gunicorn -k uvicorn.workers.UvicornWorker main:app
    

Dependency Installation

  • Using Requirements File

    Create a requirements.txt:

      fastapi
      uvicorn
      pydantic
    

    Install dependencies:

      pip install -r requirements.txt
    

Quick Revision Notes

What is FastAPI?

  • A modern Python web framework for building APIs.

  • Leverages Python type hints for data validation.

  • Provides automatic API documentation.

Key Features

  • High Performance: Comparable to NodeJS and Go.

  • Ease of Use: Simple and intuitive syntax.

  • Automatic Docs: Swagger UI and ReDoc.

  • Type Safety: Ensures data validity with Pydantic.

Basic Components

  • FastAPI App: Created with FastAPI().

  • Path Operations: Decorators like @app.get(), @app.post(), etc.

  • Pydantic Models: Define data schemas.

  • Dependency Injection: Manage dependencies cleanly.

CRUD Operations

  • GET: Retrieve data.

  • POST: Create new data.

  • PUT: Update existing data.

  • DELETE: Remove data.

Common Commands

  • Install FastAPI and Uvicorn:

      pip install fastapi uvicorn
    
  • Run the Application:

      uvicorn main:app --reload
    
  • Access Swagger UI:

    Navigate to http://127.0.0.1:8000/docs.

Best Practices

  • Use Pydantic Models: For request and response validation.

  • Async Functions: Leverage async def for non-blocking I/O operations.

  • Error Handling: Use HTTPException for custom error responses.

  • Dependency Injection: Simplify code and enhance testability.

  • Environment Variables: Manage configuration settings securely.

Tips

  • Auto Reload: Use --reload during development for convenience.

  • Interactive Docs: Utilize Swagger UI to test endpoints quickly.

  • Type Hints: Provide explicit types for better validation and documentation.

  • Modular Code: Organize routes and models in separate files for larger projects.


Remember: FastAPI combines speed, ease of use, and powerful features to make API development in Python efficient and enjoyable. Practice by building your own APIs, exploring advanced features like middleware, background tasks, and authentication to deepen your understanding.


Additional Resources


0
Subscribe to my newsletter

Read articles from Sai Prasanna Maharana directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sai Prasanna Maharana
Sai Prasanna Maharana