LectureThree
LectureThree
What is FastAPI?
FastAPI is a modern, high-performance web framework for building APIs (Application
Programming Interfaces) with Python. In simple terms, it’s a tool that helps you create the
“behind-the-scenes” part of a web app—the part that handles requests (like asking for data) and
sends back responses (like giving you that data). It’s designed to be:
Imagine FastAPI as a super-smart librarian who quickly finds and delivers the exact book (data)
you ask for from a huge library (your app)!
Page 1 of 43
fastapi
Quick Recap
Page 2 of 43
fastapi
What : FastAPI is a Python tool for building fast and simple APIs.
Why : It’s quick, easy, gives you free documentation, and checks your data so there are fewer errors.
Example : It’s perfect for something like a student grade tracker—making it easy to manage grades with
clean, reliable code.
What is Pip?
Pip is like a delivery service for Python. It’s a tool that helps you install and manage libraries (pre-
written code) that you can use in your projects. For example, instead of writing all the code for a
web framework from scratch, you can use pip to bring FastAPI into your project with a single
command.
Analogy : Think of pip as a helpful assistant who fetches the tools you need from a giant warehouse (the
Python Package Index, or PyPI) so you can focus on building your project.
Analogy : Imagine you’re studying for two different subjects—math and history. You wouldn’t mix your
math notes with your history notes; you’d keep them in separate folders. Similarly, virtual environments
keep your project’s libraries organized and separate.
Page 3 of 43
fastapi
If it shows a version number (e.g., Python 3.9.5), you’re good to go!
Explanation : mkdir creates a new directory (folder), and cd moves you into that directory.
macOS/Linux :
Explanation : This creates a new virtual environment named myenv . You can name it anything, but
myenv or venv are common choices.
macOS/Linux :
source myenv/bin/activate
Tip : Once activated, you’ll see (myenv) at the start of your command line, indicating you’re working
inside the virtual environment.
Explanation : This command tells pip to fetch and install FastAPI (the web framework) and Uvicorn (the
server that will run your app).
What is Uvicorn?
Uvicorn is the server that powers your FastAPI app. It’s like the engine that runs your application, allowing it to
listen for requests from users and send back responses. Without Uvicorn, your FastAPI app wouldn’t be able to
interact with the outside world.
Analogy : If FastAPI is a chef preparing delicious meals, Uvicorn is the waiter who takes orders from
customers and serves the food. Together, they make your app run smoothly!
Quick Recap
Pip : A tool to install Python libraries easily.
Vir tual Environment : A private space for your project’s libraries to avoid conflicts.
Installation Steps :
1. Check if Python is installed.
2. Open the command prompt.
3. Create and navigate to a project directory.
4. Create a virtual environment.
5. Activate the virtual environment.
6. Install FastAPI and Uvicorn with pip install fastapi uvicorn .
Uvicorn : The server that runs your FastAPI app.
@app.get("/") # Define what happens when someone visits the main page
async def say_hello(): # A function that runs when the main page is visited
return {"message": "Hello, World!"} # Send back this message
Page 5 of 43
fastapi
Detailed Breakdown of the Code
Let’s go line by line so you understand everything:
from fastapi import FastAPI :
This imports the FastAPI class from the fastapi package you installed. It’s the main tool we’ll
use to build the API.
app = FastAPI() :
This creates an instance of the FastAPI class and names it app . Think of app as your API project
—it’s where everything happens.
@app.get("/") :
This is called a decorator . It tells FastAPI: "When someone uses the HTTP GET method to visit
the root URL ( / ), run the function below."
The / means the main page of your API (like the homepage of a website).
def say_hello(): :
This defines a function called say_hello . It’s what runs when someone visits the root URL.
No input is needed here—it’s just a simple response.
return {"message": "Hello, World!"} :
This sends back a response in JSON format (a common way to send data over the internet).
The response is a dictionary: {"message": "Hello, World!"} , which looks like {"message":
"Hello, World!"} in the browser.
Page 6 of 43
fastapi
What does this mean?
uvicorn : The server that runs your API.
main:app : Tells Uvicorn to use the app object from main.py .
--reload : Automatically restarts the server if you edit the code (great for testing!).
3. Check the output :
You should see something like:
This means your API is running! http://127.0.0.1:8000 is the address where it lives.
Page 9 of 43
fastapi
class Item(BaseModel):
name: str
price: float
@app.post("/items/")
async def create_item(item: Item):
return item
The docs will show the exact structure of item (e.g., {"name": "string", "price": 0.0} ).
FastAPI is a tool to build APIs (ways for apps to talk to each other) quickly and easily. Two super
important ideas in FastAPI are routes and path parameters . Let’s make them simple to
understand with examples that anyone can follow!
Think of a website:
/home might show the homepage.
/about might show an "About Us" page.
In an API:
/students could list all students.
/grades could show all grades.
Each route connects to a function that does something—like giving back data!
Code:
Page 11 of 43
fastapi
app = FastAPI()
@app.get("/students/{student_id}")
async def get_student(student_id: int):
return {"student_id": student_id, "name": "Olu Jones"}
What’s Happening?
1. Route : /students/{student_id}
{student_id} is the path parameter—it’s a placeholder for whatever number you put in the
URL.
2. Function : get_student(student_id: int)
Takes the number from the URL (like 42) and says it must be an integer (a whole number like 1,
2, 3—not "abc").
FastAPI checks this for you!
3. Result : Returns a dictionary (data) with the student_id and a name.
Try It:
Run your app with:
Visit: http://127.0.0.1:8000/students/42
You’ll see:
{"student_id": 4212, "name": "Olu Jones"}
Try: http://127.0.0.1:8000/students/abc
FastAPI says: "Nope! That’s not a number!" (Error: "Input should be a valid integer").
Code:
Page 12 of 43
fastapi
@app.get("/greet/{username}")
async def greet(username: str):
return {"message": f"Hello, {username}!"}
What’s Happening?
1. Route : /greet/{username}
{username} is the path parameter—it can be any word like "Adiza" or "Nelson".
2. Function : greet(username: str)
Takes the text from the URL and says it’s a string (text, not a number).
3. Result : Returns a friendly greeting.
Try It:
Visit: http://127.0.0.1:8000/greet/Adiza
You’ll see:
{"message": "Hello, Adiza!"}
Visit: http://127.0.0.1:8000/greet/Nelson
You’ll see:
Code:
@app.get("/students/{student_id}/subjects/{subject}")
async def get_subject(student_id: int, subject: str):
return {"student_id": student_id, "subject": subject, "grade": "B"}
What’s Happening?
1. Route : /students/{student_id}/subjects/{subject}
Two parameters: {student_id} (a number) and {subject} (text).
2. Function : get_subject(student_id: int, subject: str)
Page 13 of 43
fastapi
Takes both values from the URL.
3. Result : Returns the student ID, subject, and a grade.
Try It:
Visit: http://127.0.0.1:8000/students/7/subjects/science
You’ll see:
Visit: http://127.0.0.1:8000/students/10/subjects/art
You’ll see:
@app.get("/students/new")
async def new_student():
return {"message": "Adding a new student"}
Visit: http://127.0.0.1:8000/students/new
Problem: FastAPI thinks "new" is a student_id and gives an error ("new" isn’t a number!).
@app.get("/students/{student_id}")
async def get_student(student_id: int):
return {"student_id": student_id, "name": "Alusine"}
Visit: http://127.0.0.1:8000/students/new
Page 14 of 43
fastapi
You’ll see:
Visit: http://127.0.0.1:8000/students/5
You’ll see:
{"student_id": 5, "name": "Alusine"}
Try It Yourself!
1. Make a route /books/{book_id} that returns {"book_id": book_id, "title": "Cool Book"} .
2. Make a route /hello/{name}/{age} that returns {"message": "Hi [name], you are [age] years
old!"} .
Page 15 of 43
fastapi
Think of it like ordering food :
The main route ( /pizza ) is like saying, "I want pizza."
Query parameters ( ?topping=cheese&size=large ) are like adding, "Make it with extra cheese
and large size!"
In a URL, they look like this:
http://example.com/pizza?topping=cheese&size=large
Code:
from fastapi import FastAPI
app = FastAPI()
@app.get("/grades/")
async def get_grades(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}
What’s Happening?
1. Route : /grades/
This is the main URL for getting grades.
2. Quer y Parameters : skip: int = 0 and limit: int = 10
skip : How many items to skip (default is 0, so start from the beginning).
limit : How many items to show (default is 10, so show up to 10 grades).
The = 0 and = 10 make them optional —if you don’t provide them, FastAPI uses the defaults.
3. Function : Returns a dictionary with the skip and limit values.
Try It:
Run your app:
uvicorn main:app --reload
Visit: http://127.0.0.1:8000/grades/?skip=5&limit=3
Page 16 of 43
fastapi
You’ll see:
{"skip": 5, "limit": 3}
Try: http://127.0.0.1:8000/grades/
Since you didn’t add skip or limit , you’ll get the defaults:
Code:
@app.get("/students/")
async def get_students(name: str = None):
if name:
return {"message": f"Found student: {name}"}
return {"message": "No name provided, showing all students"}
What’s Happening?
1. Route : /students/
2. Quer y Parameter : name: str = None
name is optional (default is None , meaning no name was given).
It’s a string, so you can pass text like "Adeola" or "Sarah".
3. Function :
If name is provided, it says, "Found student: [name]."
If no name , it says, "Showing all students."
Try It:
Visit: http://127.0.0.1:8000/students/?name=Adeola
You’ll see:
{"message": "Found student: Adeola"}
Visit: http://127.0.0.1:8000/students/
You’ll see:
Page 17 of 43
fastapi
Code:
@app.get("/books/")
async def get_books(category: str = "all", max_price: float = 100.0):
return {"category": category, "max_price": max_price}
What’s Happening?
1. Route : /books/
2. Quer y Parameters :
category: str = "all" : The book category (default is "all").
max_price: float = 100.0 : The maximum price (default is 100.0, and it can be a decimal).
3. Function : Returns the category and max price you provided.
Try It:
Visit: http://127.0.0.1:8000/books/?category=fiction&max_price=20.99
You’ll see:
{"category": "fiction", "max_price": 20.99}
Visit: http://127.0.0.1:8000/books/?category=scifi
You’ll see:
Visit: http://127.0.0.1:8000/books/
You’ll see:
{"category": "all", "max_price": 100.0}
Code:
@app.get("/students/{student_id}/grades/")
async def get_student_grades(student_id: int, subject: str = None, min_score: int = 0):
return {"student_id": student_id, "subject": subject, "min_score": min_score}
What’s Happening?
1. Route : /students/{student_id}/grades/
{student_id} is a path parameter (a number in the URL).
2. Quer y Parameters :
subject: str = None : Optional subject to filter grades (e.g., "math").
min_score: int = 0 : Optional minimum score to show.
3. Function : Returns the student ID, subject (if provided), and minimum score.
Try It:
Visit: http://127.0.0.1:8000/students/42/grades/?subject=math&min_score=80
You’ll see:
Visit: http://127.0.0.1:8000/students/7/grades/
You’ll see:
Try It Yourself!
1. Make a route /movies/ with query parameters genre: str = "all" and year: int = 2020 . Return
{"genre": genre, "year": year} .
2. Make a route /courses/{course_id}/ with a query parameter level: str = "beginner" . Return
{"course_id": course_id, "level": level} .
What is Pydantic?
Pydantic is a Python library that helps you define and validate data . It’s like a super-smart librarian who
checks that every book (data) you bring to the library (your app) has the right title, author, and format before
letting it in.
Define Data : You tell Pydantic what your data should look like (e.g., a student must have a name and
age).
Validate Data : Pydantic checks if the data matches your rules (e.g., is the age a number?).
Error Handling : If something’s wrong (e.g., someone sends "pizza" instead of a number), Pydantic
catches it and tells you.
Pydantic is used a lot in FastAPI to make sure the data your API receives is correct and safe.
Page 20 of 43
fastapi
Code:
from pydantic import BaseModel
class Student(BaseModel):
name: str
age: int
grade: float = None # Optional field
What’s Happening?
1. Impor t BaseModel :
BaseModel is the foundation of Pydantic models. Your model inherits from it.
2. Define the Model :
class Student : Creates a model called Student .
name: str : Says the student must have a name that’s a string (text).
age: int : Says the student must have an age that’s an integer (whole number).
grade: float = None : Says grade is optional (it can be a decimal number or nothing).
3. Validation :
Pydantic checks that any data you give it matches this structure.
Try It:
Let’s test the model in Python (you can run this in a Python file or interactive shell).
Code:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Student(BaseModel):
name: str
age: int
@app.post("/students/")
def create_student(student: Student):
return {"message": "Student added", "data": student}
What’s Happening?
1. Model : The Student model says the data must have a name (string) and age (integer).
2. Route : The /students/ route accepts POST requests (used to send data).
3. Parameter : student: Student means FastAPI expects data that matches the Student model.
4. Validation : FastAPI uses Pydantic to check the data. If it’s wrong, it sends an error.
Try It:
Run your app:
uvicorn main:app --reload
Use a tool like Postman , curl , or the Swagger UI ( http://127.0.0.1:8000/docs ) to send this JSON:
You’ll get:
{"message": "Student added", "data": {"name": "Alex", "age": 18}}
Page 22 of 43
fastapi
{"detail": [{"loc": ["body", "age"], "msg": "Input should be a valid integer", "type":
"type_error.integer"}]}
Code:
from pydantic import BaseModel
class Book(BaseModel):
title: str
author: str
price: float = 10.0 # Default value
in_stock: bool = True # Default value
Try It:
# Create a book with all fields
book1 = Book(title="Python 101", author="Jane Doe", price=15.99, in_stock=False)
print(book1) # Output: title='Python 101' author='Jane Doe' price=15.99 in_stock=False
Code:
Page 23 of 43
fastapi
class Course(BaseModel):
name: str
credits: int
class Student(BaseModel):
name: str
age: int
courses: List[Course] # A list of Course models
# Test it
student = Student(
name="Mia",
age=19,
courses=[
Course(name="Math", credits=3),
Course(name="Science", credits=4)
]
)
print(student)
Output:
name='Mia' age=19 courses=[Course(name='Math', credits=3), Course(name='Science', credits=4)]
Try It Yourself!
1. Create a Pydantic model Car with fields brand: str , year: int , and color: str = "Blue" . Test it
with valid and invalid data.
2. Make a FastAPI route /cars/ that accepts a Car model and returns {"message": "Car added",
"data": car} .
Pydantic is your data’s best friend—it keeps everything organized and safe!
Page 24 of 43
fastapi
FastAPI uses Pydantic models to define what this data should look like and to ensure it’s correct.
Code:
Page 25 of 43
fastapi
app = FastAPI()
class Student(BaseModel):
name: str
age: int
grade: float = None # Optional field
@app.post("/students/")
def create_student(student: Student):
return {"message": "Student created", "data": student}
What’s Happening?
1. Pydantic Model : Student
name: str : The student’s name must be text (e.g., "Alusine").
age: int : The age must be a whole number (e.g., 21).
grade: float = None : The grade is optional (can be a decimal like 88.5 or omitted).
2. Route : @app.post("/students/")
This sets up a POST endpoint at /students/ .
POST is used for sending or creating data.
3. Parameter : student: Student
FastAPI expects the request body to match the Student model.
Pydantic validates the data and converts it into a Python object.
4. Function : create_student
Returns a message and the student data you sent.
Try It:
Run your app:
uvicorn main:app --reload
Page 26 of 43
fastapi
{"message": "Student created", "data": {"name": "Alusine", "age": 21, "grade": 88.5}}
Code:
from pydantic import BaseModel
class Book(BaseModel):
title: str
author: str
price: float
in_stock: bool = True # Optional, defaults to True
@app.post("/books/")
def create_book(book: Book):
return {"message": "Book added", "data": book}
What’s Happening?
1. Model : Book
title and author are required strings.
price is a required decimal number.
Page 27 of 43
fastapi
in_stock is optional (defaults to True if not provided).
2. Route : @app.post("/books/")
Accepts POST requests to add a book.
3. Function : Returns a confirmation and the book data.
Try It:
In Swagger UI ( http://127.0.0.1:8000/docs ):
Send:
{"title": "FastAPI Basics", "author": "Hawa", "price": 29.99}
You’ll get:
{"message": "Book added", "data": {"title": "FastAPI Basics", "author": "Hawa", "price":
29.99, "in_stock": true}}
Code:
from pydantic import BaseModel
from typing import List
class Course(BaseModel):
name: str
credits: int
class Student(BaseModel):
name: str
age: int
courses: List[Course] # A list of courses
@app.post("/students-with-courses/")
def create_student(student: Student):
return {"message": "Student and courses added", "data": student}
Page 28 of 43
fastapi
What’s Happening?
1. Models :
Course : Defines a course with a name and credits .
Student : Includes a courses field that’s a list of Course models.
2. Route : Accepts a POST request with nested data.
3. Validation : Pydantic checks the entire structure, including the courses.
Try It:
In Swagger UI:
Send:
{
"name": "Valentine",
"age": 22,
"courses": [
{"name": "Biology", "credits": 3},
{"name": "History", "credits": 4}
]
}
You’ll get:
{
"message": "Student and courses added",
"data": {
"name": "Valentine",
"age": 22,
"courses": [
{"name": "Biology", "credits": 3},
{"name": "History", "credits": 4}
]
}
}
Try It Yourself!
1. Create a Pydantic model Product with fields name: str , price: float , and quantity: int = 1 .
Make a POST route /products/ that returns {"message": "Product added", "data": product} .
2. Create a model Order with a customer: str and items: List[str] . Make a POST route /orders/
that accepts an Order and returns it.
Code:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Student(BaseModel):
name: str
age: int
grade: float = None # Optional field
@app.get("/students/{student_id}", response_model=Student)
def get_student(student_id: int):
return {"name": "Kubra", "age": 79, "grade": 92.5}
What’s Happening?
1. Pydantic Model : Student
Defines the structure: name (string), age (integer), and grade (optional float).
2. Route : @app.get("/students/{student_id}")
A GET endpoint that takes a student_id as a path parameter.
3. Response Model : response_model=Student
Tells FastAPI that the response must match the Student model.
Pydantic ensures the output has the right fields and types.
4. Function : get_student
Returns a dictionary with Kubra’s details.
Try It:
Run your app:
Visit: http://127.0.0.1:8000/students/42
You’ll see:
Page 31 of 43
fastapi
Code:
@app.get("/students/{student_id}/details", response_model=Student)
def get_student_details(student_id: int):
return {
"name": "Moore",
"age": 20,
"grade": 88.0,
"secret_info": "Top secret!" # This won’t be included
}
What’s Happening?
1. Response Model : response_model=Student
Only includes fields from the Student model ( name , age , grade ).
Ignores extra fields like secret_info .
2. Function : Returns a dictionary with Moore’s details, plus some extra data.
Try It:
Visit: http://127.0.0.1:8000/students/7/details
You’ll see:
{"name": "Moore", "age": 20, "grade": 88.0}
Code:
class StudentInput(BaseModel):
name: str
age: int
grade: float = None
class StudentOutput(BaseModel):
name: str
age: int
message: str # Custom message in the response
@app.post("/students/", response_model=StudentOutput)
def create_student(student: StudentInput):
return {
"name": student.name,
"age": student.age,
"message": f"Welcome, {student.name}!",
"grade": student.grade # This won’t be included
}
What’s Happening?
1. Models :
StudentInput : Defines the data sent to the API (request body).
StudentOutput : Defines the data sent back (response).
2. Route : @app.post("/students/")
Accepts a POST request with a StudentInput and returns a StudentOutput .
3. Function : Returns Osman’s details with a welcome message, but grade is filtered out.
Try It:
In Swagger UI ( http://127.0.0.1:8000/docs ):
Send this JSON to the /students/ POST endpoint:
You’ll get:
Page 33 of 43
fastapi
Why It’s Cool:
You can have different models for input and output, giving you total control over what users see!
Code:
from pydantic import BaseModel
from typing import List
class Course(BaseModel):
name: str
credits: int
class StudentWithCourses(BaseModel):
name: str
age: int
courses: List[Course]
@app.get("/students/{student_id}/courses", response_model=StudentWithCourses)
def get_student_courses(student_id: int):
return {
"name": "Kubra",
"age": 19,
"courses": [
{"name": "Math", "credits": 3},
{"name": "Science", "credits": 4}
],
"extra": "Hidden" # This won’t be included
}
What’s Happening?
1. Models :
Course : Defines a course with name and credits .
StudentWithCourses : Includes a list of Course models.
2. Response Model : Ensures the response matches StudentWithCourses .
3. Function : Returns Kubra’s details with courses, but extra is filtered out.
Try It:
Visit: http://127.0.0.1:8000/students/10/courses
You’ll see:
Page 34 of 43
fastapi
{
"name": "Kubra",
"age": 19,
"courses": [
{"name": "Math", "credits": 3},
{"name": "Science", "credits": 4}
]
}
Try It Yourself!
1. Create a Product model with name: str , price: float , and in_stock: bool . Make a GET route
/products/{product_id} with response_model=Product that returns {"name": "Laptop",
"price": 999.99, "in_stock": true} .
2. Create a Teacher model with name: str and subjects: List[str] . Make a POST route
/teachers/ that accepts a Teacher and returns a Teacher with a response_model that includes a
message: str .
app = FastAPI()
class Todo(BaseModel):
task: str
completed: bool = False
todos = []
@app.get("/todos/")
def list_todos(skip: int = 0, limit: int = 10):
return todos[skip:skip + limit]
@app.post("/todos/")
def add_todo(todo: Todo):
todos.append(todo)
return {"message": "Todo added", "todo": todo}
What’s Happening?
1. Impor ts :
FastAPI : The main tool for building your API.
BaseModel : From Pydantic, used to define the structure of your to-do tasks.
2. Pydantic Model : Todo
task: str : The task description (e.g., "Do homework").
completed: bool = False : Whether the task is done (defaults to False , meaning not done).
3. Storage : todos = []
A simple list to store all your to-do tasks (like a digital notepad).
4. GET Route : @app.get("/todos/")
Lists tasks with skip (start point) and limit (how many to show).
Example: skip=2 and limit=3 shows tasks 3, 4, and 5.
5. POST Route : @app.post("/todos/")
Adds a new task to the todos list.
Page 36 of 43
fastapi
Returns a message and the task you added.
What’s this?
uvicorn : The server that runs your API.
main:app : Tells Uvicorn to use the app from main.py .
--reload : Updates the server when you change the code.
You’ll see something like:
5. Click “Execute.”
6. You’ll see the response:
Page 37 of 43
fastapi
{
"message": "Todo added",
"todo": {
"task": "Finish math homework",
"completed": false
}
}
Why? Pydantic checked that completed must be true or false , not text.
Page 38 of 43
fastapi
[
{"task": "Finish math homework", "completed": false},
{"task": "Read history book", "completed": false},
{"task": "Clean room", "completed": true}
]
Page 39 of 43
fastapi
@app.get("/todos/")
def list_todos(skip: int = 0, limit: int = 10, completed: bool = None):
if completed is not None:
filtered = [todo for todo in todos if todo.completed == completed]
return filtered[skip:skip + limit]
return todos[skip:skip + limit]
Page 40 of 43
fastapi
Try It Yourself!
1. Add three tasks using POST, then use GET to list them with skip=1 and limit=2 .
2. Try the challenges above (add priority , filter by completed , or add a DELETE route).
3. Show your API to a friend and explain how it works!
Required Tasks
Task 1: Add a New Book (POST)
Endpoint : POST /books/
Description : Add a new book to the library.
Requirements :
Use Book Pydantic model for validation.
Append book to books list.
Return message and added book.
Example Request Body :
{"title": "Python Programming", "author": "Alusine", "price": 29.99, "in_stock": true}
Example Response :
{"message": "Book added", "book": {"title": "Python Programming", "author": "Alusine", "price":
29.99, "in_stock": true}}
Page 41 of 43
fastapi
Example Response :
{"message": "Book updated", "book": {"title": "Advanced Python", "author": "Valentine", "price":
39.99, "in_stock": false}}
Submission Instructions
Submit :
main.py with all code.
Screenshots of Swagger UI showing:
POST /books/ success.
GET /books/ with query parameters.
GET /books/{book_id} success.
PUT /books/{book_id} success.
Format : Zip files as YourName_LibraryAPI.zip .
Submit To : Class-rep.
Tips
Start with POST and GET, then add others.
Test each endpoint in Swagger UI.
Add comments to your code.
Review lecture notes if stuck.
Page 43 of 43