This repository contains code and examples from the O'Reilly course Ultimate Guide to FastAPI and Backend Development.
- Course Link: https://learning.oreilly.com/course/ultimate-guide-to/9781806101337/
- Status: Chapter 9 completed
- Python: 3.7+
- Framework: FastAPI
- Database: SQLite with SQLModel ORM
- Async: Python asyncio with TaskGroup
A hands-on learning project for FastAPI and backend development. This application provides a complete shipment management system with REST API endpoints, demonstrating best practices for route creation, request/response validation, database integration, and interactive API documentation.
- β‘ FastAPI app with async/await support
- ποΈ SQLite database with SQLModel ORM
- π¦ Complete CRUD operations for shipment management
- β Pydantic models for request/response validation
- π Automatic database table creation on startup
- π Interactive Swagger UI and ReDoc documentation
- π Scalar API reference support
- π Auto-reload development server
- β±οΈ Concurrent request handling with asyncio
- π Advanced async patterns with TaskGroup
- Python 3.7 or higher
pip(Python package installer)- Virtual environment (recommended)
git clone https://github.com/<your-account>/FastAPI_and_Backend_Development_Course.git
cd FastAPI_and_Backend_Development_CourseWindows:
python -m venv venv
.\venv\Scripts\activatemacOS/Linux:
python -m venv venv
source venv/bin/activatepip install fastapi uvicorn sqlmodel sqlalchemy scalar-fastapi richOr install from requirements file (if available):
pip install -r requirements.txtStart the FastAPI development server:
fastapi devOr using uvicorn directly:
uvicorn app.main:app --reloadThe application will be available at:
- API: http://127.0.0.1:8000
- Swagger UI: http://127.0.0.1:8000/docs
- ReDoc: http://127.0.0.1:8000/redoc
- Scalar API Reference: http://127.0.0.1:8000/scalar
This project uses Scalar as the primary API documentation tool, alongside traditional Swagger UI and ReDoc options.
Scalar is a modern, beautiful alternative to Swagger UI that provides:
- π¨ Clean, modern user interface
- π± Responsive design optimized for desktop and mobile
- π Advanced search and filtering
- πΎ Request history and examples
- π§ͺ Built-in API testing capabilities
- π Better readability for complex API schemas
Access Scalar: http://127.0.0.1:8000/scalar
The Scalar documentation is integrated via the scalar_fastapi package and provides an intuitive way to explore and test all available endpoints.
- Swagger UI (Traditional): http://127.0.0.1:8000/docs
- ReDoc (Alternative UI): http://127.0.0.1:8000/redoc
All documentation formats display the same API schema and are automatically generated from the FastAPI application code.
FastAPI_and_Backend_Development_Course/
βββ app/
β βββ __init__.py # App package initialization
β βββ main.py # FastAPI application and route handlersβ βββ async.py # Async programming examples with TaskGroupβ βββ schemas.py # Pydantic/SQLModel models
β βββ database.py # Legacy database utility class
β βββ database/
β βββ __init__.py
β βββ models.py # SQLModel database models
β βββ session.py # SQLAlchemy session management
βββ venv/ # Virtual environment
βββ test.py # Test script
βββ README.md # This file
βββ sqlite.db # SQLite database (generated on first run)
This project demonstrates advanced asynchronous programming patterns using Python's asyncio module.
The async.py module showcases how to handle multiple API requests concurrently using asyncio.TaskGroup:
Key Concepts:
async def- Defines asynchronous functionsawait- Waits for async operations without blockingasyncio.TaskGroup- Groups multiple async tasks for concurrent executionasyncio.sleep()- Non-blocking delay (simulates I/O operations)time.perf_counter()- Measures performance and execution time
Example Usage:
python app/async.pyOutput Example:
>> handling GET /shipment?id=1
>> handling PATCH /shipment?id=4
>> handling GET /shipment?id=3
<< response GET /shipment?id=1
<< response PATCH /shipment?id=4
<< response GET /shipment?id=3
Time Taken : 1.05s
The TaskGroup allows all three requests to execute concurrently, reducing total execution time compared to sequential requests.
All endpoints in main.py are defined as async functions, enabling FastAPI to handle multiple requests concurrently:
@app.get("/shipment")
async def get_shipment(id: int, session: SessionDep) -> Shipment:
# FastAPI manages concurrent requests automatically
pass
@app.post("/shipment")
async def create_shipment(shipment: ShipmentCreate, session: SessionDep) -> dict:
# Multiple requests are handled concurrently by Uvicorn
passFastAPI automatically manages the event loop and concurrency for HTTP requests using Uvicorn (ASGI server).
Available status values:
pending- Shipment awaiting dispatchin_transit- Shipment is on the waydelivered- Shipment has been deliveredplaced- Order has been placedout_for_delivery- Shipment is out for delivery
Base model with core shipment fields:
content(str, max 50 chars) - Description of shipment contentweight(float) - Weight in kg (must be > 0 and β€ 25)destination(str, max 100 chars) - Delivery destinationzip_code(int, optional) - Postal code (auto-generated if not provided)
Complete database model inheriting from BaseShipment:
id(int) - Primary keyshipment_status(ShipmentStatus) - Current statusestimated_delivery(datetime) - Estimated delivery date
Used for POST requests (inherits from BaseShipment)
Used for PATCH requests (all fields optional):
shipment_status(ShipmentStatus, optional)estimated_delivery(datetime, optional)
GET /shipment?id=1Parameters:
id(query, required) - Shipment ID
Response (200):
{
"id": 1,
"content": "laptop",
"weight": 2.5,
"destination": "New York",
"zip_code": 10001,
"shipment_status": "in_transit",
"estimated_delivery": "2026-04-10T15:30:00"
}GET /shipment/latestResponse (200):
{
"id": 5,
"content": "sofa",
"weight": 4.1,
"destination": "Vienna",
"zip_code": 1010,
"shipment_status": "in_transit",
"estimated_delivery": "2026-04-12T10:00:00"
}POST /shipmentRequest Body:
{
"content": "monitor",
"weight": 3.5,
"destination": "London",
"zip_code": 12345
}Response (201):
{
"id": 6
}PATCH /shipment?id=1Parameters:
id(query, required) - Shipment ID to update
Request Body:
{
"shipment_status": "delivered",
"estimated_delivery": "2026-04-08T14:00:00"
}Response (200):
{
"id": 1,
"content": "laptop",
"weight": 2.5,
"destination": "New York",
"zip_code": 10001,
"shipment_status": "delivered",
"estimated_delivery": "2026-04-08T14:00:00"
}DELETE /shipment?id=1Parameters:
id(query, required) - Shipment ID to delete
Response (200):
{
"detail": "Shipment with ID 1 has been deleted"
}The application uses SQLite with SQLModel ORM. The database is automatically created on first run with the required shipment table.
Database file: sqlite.db (created in project root)
CREATE TABLE IF NOT EXISTS shipment (
id INTEGER PRIMARY KEY,
content TEXT NOT NULL,
weight REAL NOT NULL,
destination TEXT NOT NULL,
shipment_status TEXT NOT NULL,
zip_code INTEGER,
estimated_delivery DATETIME NOT NULL
)Changes to code files automatically reload the server when using fastapi dev or uvicorn with --reload flag.
To test the asynchronous programming examples from Chapter 9:
python app/async.pyThis demonstrates concurrent task execution using Python's asyncio module and TaskGroup for managing multiple async operations.
Run the test file:
python test.py- fastapi - Web framework
- uvicorn - ASGI server
- sqlmodel - SQL ORM combining SQLAlchemy + Pydantic
- sqlalchemy - Database toolkit
- scalar-fastapi - Modern API documentation
- rich - Beautiful terminal output formatting
This is a learning project based on the O'Reilly course. Follow the course terms for usage.
This is a learning repository. Feel free to fork and experiment! }
**POST /shipment** (request body):
```json
{
"content": "books",
"weight": 1.2,
"destination": "Tokyo"
}
Response:
{
"id": 12085
}- Swagger:
http://127.0.0.1:8000/docs - ReDoc:
http://127.0.0.1:8000/redoc
app/
βββ __init__.py
βββ main.py # FastAPI app and API endpoints
βββ schemas.py # Pydantic models for request/response validation
βββ database.py # SQLite database logic and persistence
- Update
app/main.pyto add new endpoints and route logic. - Use
pydanticmodels in future enhancements for request/response validation.
- Fork the repository
- Create branch
feature/<name> - Add or update endpoints and tests
- Open Pull Request
Educational use only for O'Reilly course practice.