0% found this document useful (0 votes)
8 views43 pages

LectureThree

FastAPI is a modern Python web framework designed for building fast and efficient APIs, offering features like automatic documentation and data validation. It simplifies the development process by allowing easy coding and testing through interactive tools like Swagger UI and ReDoc. The document provides a comprehensive guide on installing FastAPI, creating a simple API, and understanding its core concepts such as routes and path parameters.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views43 pages

LectureThree

FastAPI is a modern Python web framework designed for building fast and efficient APIs, offering features like automatic documentation and data validation. It simplifies the development process by allowing easy coding and testing through interactive tools like Swagger UI and ReDoc. The document provides a comprehensive guide on installing FastAPI, creating a simple API, and understanding its core concepts such as routes and path parameters.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 43

fastapi

Limkokwing University of Creative Technology (LUCT) ⚙

Object Oriented Programming 2


Lecture 1: Introduction to FASTAPI
Prepared By Alpha Omar Leigh (BSc, MSc)

What is FastAPI and Why Use It?

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:

Fast : It works quickly, so your app doesn’t lag.


Simple : You can write code easily without getting confused.
Helpful : It comes with cool features like automatic documentation.

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

Why Use FastAPI?


Here’s why FastAPI is awesome and worth using:

a. Super Fast and Easy to Use


Speed : FastAPI is built to handle tons of requests super fast, thanks to the tools it uses (Starlette and
Pydantic).
Ease : Writing code in FastAPI is like writing regular Python functions—nothing too tricky! You tell it what
to do, and it does it.

b. Automatic Interactive Documentation


What’s This? : FastAPI creates a webpage that explains your API and lets you test it right in your
browser.
Why It Rocks : You don’t have to write extra instructions for your API—FastAPI does it for you. It’s like
getting free homework answers!

c. Data Validation with Type Hints


Type Hints : In Python, you can say what kind of data you expect (like numbers or text). For example,
age: int means "age must be a number."
Validation : FastAPI checks if the data matches what you expect. If someone sends "hello" instead of a
number for age , FastAPI says, “Nope, try again!” This keeps your app bug-free.

Real-World Example: Student Grade Tracker


Let’s say you’re building an app where students can check or update their grades. Here’s how FastAPI makes it
simple:
Get Grades : You make a route like /grades/123 to see the grades for student ID 123.
Add Grades : You create another route like /grades/ to add a new grade, like “95” for a test.
No Mistakes : If someone tries to add “pizza” as a grade, FastAPI catches it and says, “That’s not a
number!”
With FastAPI, you can build this app fast, test it easily with the automatic documentation, and trust that it’ll work
smoothly.

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.

Getting Started with FastAPI: Installation

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.

What are Virtual Environments?


A virtual environment is like a private workspace for your Python project. It keeps all the
libraries and dependencies (like FastAPI and Uvicorn) separate from other projects you might be
working on. This way, if one project needs a specific version of a library, it won’t mess up another
project that needs a different version.

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.

Step-by-Step Installation Guide


Let’s walk through the process of setting up your environment and installing FastAPI and Uvicorn using the
command prompt. Follow these steps carefully:

Step 1: Make Sure Python is Installed


You need Python 3.6 or higher. If you don’t have Python installed, download it from python.org .
To check if Python is installed, open your command prompt (Windows) or terminal (macOS/Linux) and
type:
python --version

Page 3 of 43
fastapi
If it shows a version number (e.g., Python 3.9.5), you’re good to go!

Step 2: Open the Command Prompt or Terminal


Windows : Press Win + R , type cmd , and hit Enter.
macOS/Linux : Search for “Terminal” in your applications.

Step 3: Create a New Directory for Your Project


It’s a good idea to keep your project files organized in their own folder.
In the command prompt, type:
mkdir fastapi_project
cd fastapi_project

Explanation : mkdir creates a new directory (folder), and cd moves you into that directory.

Step 4: Create a Virtual Environment


Now, let’s create a virtual environment inside your project folder.
Windows :
python -m venv myenv

macOS/Linux :

python3 -m venv myenv

Explanation : This creates a new virtual environment named myenv . You can name it anything, but
myenv or venv are common choices.

Step 5: Activate the Virtual Environment


Before installing libraries, you need to activate the virtual environment.
Windows :
myenv\Scripts\activate

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.

Step 6: Install FastAPI and Uvicorn


Now that your virtual environment is active, you can install FastAPI and Uvicorn using pip.
In the command prompt, type:
Page 4 of 43
fastapi

pip install fastapi uvicorn

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.

Creating Your First "Hello, World!" API with FastAPI

Write the Code


Now, let’s create the API. Here’s the complete code:

# Save this in a file called main.py


from fastapi import FastAPI # Import the FastAPI tool

app = FastAPI() # Create your API 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.

Save the Code


Open your code editor.
Copy the code above.
Save it as main.py in your project folder ( my_first_api if you followed the earlier step).

Run Your API


Let’s start the API so it’s live and ready to use!
1. Go to your project folder in the terminal :
If you’re not already there, type:
cd my_first_api

2. Run the API :


Type this command and press Enter:
uvicorn main:app --reload

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:

INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

This means your API is running! http://127.0.0.1:8000 is the address where it lives.

Test It in Your Browser


Let’s see your API in action!
1. Open a web browser :
Use Chrome, Firefox, Edge, or any browser you like.
2. Visit the API :
Type this into the address bar and press Enter:
http://127.0.0.1:8000

What’s this address?


127.0.0.1 is your computer’s local IP address (also called "localhost").
8000 is the port number Uvicorn uses by default.
3. What you’ll see :
The browser should display:
{"message": "Hello, World!"}

This is the JSON response from your API!

Troubleshooting (If Something Goes Wrong)


If it doesn’t work, here are some common fixes:
Error : "uvicorn is not recognized" :
You didn’t install Uvicorn. Run pip install uvicorn again.
Nothing shows up in the browser :
Make sure you typed http://127.0.0.1:8000 correctly.
Check if the terminal says the server is running.
Page 7 of 43
fastapi
Por t already in use :
If you see an error about port 8000, stop the server (Ctrl+C in the terminal) and try:
uvicorn main:app --port 8001 --reload

Then visit http://127.0.0.1:8001 .

FastAPI Automatic Documentation: Swagger UI and ReDoc


Explained
FastAPI is a powerful Python framework that simplifies API development, and one of its best features is
automatic documentation . This means FastAPI creates an interactive guide for your API without extra effort. It
uses the OpenAPI standard and provides two tools to view this documentation: Swagger UI (at /docs ) and
ReDoc (at /redoc ). This guide will help you understand how these work and why they’re useful, especially for
students learning API development.

What is API Documentation?


API documentation is like a manual for your API. It tells users:
What endpoints (e.g., /items , /users ) your API has.
What methods (e.g., GET, POST) they support.
What inputs (parameters or data) they need.
What outputs (responses) they give back.
Good documentation makes your API easy to use. FastAPI generates this automatically, so you don’t have to
write it yourself!

How Does FastAPI Create Documentation?


FastAPI uses OpenAPI , a standard way to describe APIs. When you write your API code, FastAPI builds an
OpenAPI schema based on your routes and functions. This schema powers two interfaces:
Swagger UI : Found at /docs , it’s interactive and lets you test your API in the browser.
ReDoc : Found at /redoc , it’s a clean, readable summary of your API.
These update automatically when you change your code, keeping your docs in sync.

Swagger UI: Interactive Testing at /docs


Swagger UI is a dynamic tool that shows your API endpoints and lets you try them out.

How to Use It:


Page 8 of 43
fastapi
1. Run Your FastAPI App :

uvicorn main:app --reload

This starts your API on http://127.0.0.1:8000 .


2. Visit Swagger UI :
Open your browser and go to http://127.0.0.1:8000/docs .
You’ll see a list of all your API endpoints.
3. Explore and Test :
Click an endpoint to see its details (parameters, responses, etc.).
Hit "Tr y it out" , enter values, and click "Execute" to send a request and see the response.

ReDoc: Simple Documentation at /redoc


ReDoc offers a straightforward, readable view of your API’s documentation.

How to Use It:


1. Run Your FastAPI App (same as above).
2. Visit ReDoc :
Go to http://127.0.0.1:8000/redoc .
You’ll see a neatly formatted page with all endpoints and details.

Why Use ReDoc?


It’s less interactive than Swagger UI but great for a quick, clear overview.
Perfect for sharing with others who just need to read the docs.
For the same example above, ReDoc will list /items/{item_id} with its parameters ( item_id , q ) and
response format.

Page 9 of 43
fastapi

Why It’s Awesome for Students


No Extra Work : FastAPI does the documentation for you.
Learn by Doing : Use Swagger UI to test your API as you build it.
Better Code, Better Docs : Adding type hints (e.g., item_id: int ) or Pydantic models makes your
docs more detailed. For example:
from pydantic import BaseModel

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} ).

Key Points to Remember


Swagger UI ( /docs ) : Interactive, great for testing.
ReDoc ( /redoc ) : Simple, great for reading.
Automatic : Built from your code using OpenAPI.
Live Updates : Docs reflect changes instantly.

Understanding Routes and Path Parameters in FastAPI


Page 10 of 43
fastapi

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!

What Are Routes?


Routes are like the "addresses" of your API. They tell FastAPI what to do when someone visits a
specific URL.

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!

What Are Path Parameters?


Path parameters are variables in the URL. They let one route handle lots of different requests by
changing part of the address.

Instead of making tons of routes like:


/student1 for student 1
/student2 for student 2
You make ONE route like /students/{student_id} where {student_id} can be any number (1, 2, 42,
etc.).
This makes your API smart and flexible!

Example 1: Getting a Student by ID


Let’s start with a simple example.

Code:

Page 11 of 43
fastapi

from fastapi import 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:

uvicorn main:app --reload

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").

Why It’s Cool:


FastAPI makes sure student_id is a number without you writing extra code!

Example 2: Greeting Someone by Name


Let’s try something fun with a string (text) instead of a number.

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:

{"message": "Hello, Nelson!"}

Why It’s Cool:


One route works for ANY name!

Example 3: Two Parameters (Student and Subject)


You can use more than one path parameter. Let’s get a student’s grade for a subject.

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:

{"student_id": 7, "subject": "science", "grade": "B"}

Visit: http://127.0.0.1:8000/students/10/subjects/art
You’ll see:

{"student_id": 10, "subject": "art", "grade": "B"}

Why It’s Cool:


You can mix numbers and text in one route!

Example 4: A Special Route vs. Dynamic Route


Sometimes routes can get tricky. Let’s say you want /students/new to mean "add a new student," but you also
have /students/{student_id} .

Code (Wrong Order):


@app.get("/students/{student_id}")
async def get_student(student_id: int):
return {"student_id": student_id, "name": "Alusine"}

@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!).

Code (Right Order):


@app.get("/students/new")
async def new_student():
return {"message": "Adding a new student"}

@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:

{"message": "Adding a new student"}

Visit: http://127.0.0.1:8000/students/5
You’ll see:
{"student_id": 5, "name": "Alusine"}

Why It’s Cool:


Put specific routes (like /students/new ) BEFORE dynamic ones (like /students/{student_id} ) to avoid mix-
ups!

Key Points to Remember


Routes are the URLs your API listens to (like /students ).
Path parameters are variables in the URL (like {student_id} ) that make routes flexible.
FastAPI checks types (like int or str ) for you—so your API stays safe and simple.
Order matters: Specific routes first, then dynamic ones.

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!"} .

Understanding Query Parameters in FastAPI


Query parameters are a super cool way to make your API more flexible. They let you add extra
information to a URL, like telling your API to filter or limit the data it sends back. This guide will
break it down with simple explanations and fun examples to help you understand query
parameters like a pro!

What Are Query Parameters?


Query parameters are bits of information added to the end of a URL after a question mark ( ? ).
They help you customize what your API does without changing the main route.

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

topping=cheese and size=large are query parameters.


The & connects multiple parameters.
In FastAPI, query parameters are easy to use and make your API super powerful!

Example 1: Basic Query Parameters for Grades


Let’s start with a simple example to get grades with optional limits.

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:

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

Why It’s Cool:


FastAPI grabs skip and limit from the URL automatically, and it checks they’re numbers ( int )!

Example 2: Filtering Students by Name


Let’s make an API that searches for students by name or shows all students.

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

{"message": "No name provided, showing all students"}

Why It’s Cool:


One route can handle searching or listing, depending on the query parameter!

Example 3: Multiple Query Parameters for Books


Let’s create an API to find books by category and price range.

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:

{"category": "scifi", "max_price": 100.0}

Visit: http://127.0.0.1:8000/books/
You’ll see:
{"category": "all", "max_price": 100.0}

Why It’s Cool:


You can mix different types ( str and float ) and make some parameters optional!
Page 18 of 43
fastapi

Example 4: Mixing Path and Query Parameters


Let’s combine path parameters (from the last lesson) with query parameters.

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:

{"student_id": 42, "subject": "math", "min_score": 80}

Visit: http://127.0.0.1:8000/students/7/grades/
You’ll see:

{"student_id": 7, "subject": null, "min_score": 0}

Why It’s Cool:


Path parameters (like student_id ) and query parameters (like subject ) work together to make your API super
flexible!

Key Points to Remember


Quer y parameters go after ? in the URL, like ?name=Emma or ?limit=5 .
They’re optional if you set default values (e.g., limit: int = 10 ).
FastAPI automatically pulls them from the URL and checks their types (e.g., int , str , float ).
You can mix query parameters with path parameters for powerful APIs.
Page 19 of 43
fastapi
They’re great for filtering, sorting, or customizing data.

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} .

Introduction to Pydantic: Making Data Safe and Simple in


FastAPI
Before we dive into using Pydantic with FastAPI, let’s understand what Pydantic is and why it’s so
helpful. This guide is designed to be super clear and beginner-friendly, with examples to make it
easy for students to grasp.

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.

Why Use Pydantic?


Here’s why Pydantic is awesome:
1. Saves Time : It checks data for you, so you don’t have to write lots of code to catch mistakes.
2. Keeps Things Safe : It stops bad data (like "abc" for an age) from breaking your API.
3. Works with FastAPI : Pydantic makes FastAPI’s automatic documentation (Swagger UI) even better by
showing exactly what data your API expects.
4. Easy to Use : It uses Python’s type hints (like str , int ), so it feels familiar.

Page 20 of 43
fastapi

How Does Pydantic Work?


Pydantic uses models to define the structure of your data. A model is like a blueprint that says, “This is what my
data should look like.”

Basic Example: A Student Model


Let’s create a Pydantic model for a student.

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).

# Create a valid student


student = Student(name="Josephine", age=20, grade=95.5)
print(student) # Output: name='Josephine' age=20 grade=95.5

# Try invalid data


try:
bad_student = Student(name="Zaniab", age="twenty") # "twenty" is not an int
except ValueError as e:
print(e) # Output: Validation error: Input should be a valid integer

Why It’s Cool:


Page 21 of 43
fastapi
Pydantic caught the mistake (age should be a number, not text) and told us what went wrong!

Example 1: Using Pydantic with FastAPI


Pydantic shines when you use it with FastAPI to handle data sent to your API (like when someone submits a
form).

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:

{"name": "Alex", "age": 18}

You’ll get:
{"message": "Student added", "data": {"name": "Alex", "age": 18}}

Try sending bad data:


{"name": "Alex", "age": "eighteen"}

You’ll get an error:

Page 22 of 43
fastapi

{"detail": [{"loc": ["body", "age"], "msg": "Input should be a valid integer", "type":
"type_error.integer"}]}

Why It’s Cool:


Pydantic makes sure the data is correct before your code even runs!

Example 2: Optional and Default Values


Pydantic lets you make fields optional or give them default values.

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

# Skip optional fields


book2 = Book(title="FastAPI Guide", author="John Smith")
print(book2) # Output: title='FastAPI Guide' author='John Smith' price=10.0 in_stock=True

Why It’s Cool:


You don’t have to provide every field if it has a default value, making your API more flexible!

Example 3: Nested Models


Pydantic can handle complex data, like a student with a list of courses.

Code:

Page 23 of 43
fastapi

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 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)]

Why It’s Cool:


Pydantic can validate complex structures like lists or even models inside models!

Key Points to Remember


Pydantic is a library for defining and validating data.
Models are like blueprints that describe what your data should look like.
Validation catches mistakes (like wrong data types) automatically.
FastAPI + Pydantic = Safe APIs and better documentation.
Features : Supports optional fields, default values, and complex data like lists.

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

Sending Data with POST: Request Body in FastAPI


In FastAPI, a POST request allows you to send data to your API, like adding a new student to a system. The data
is sent in the request body , typically as JSON. This guide will explain how to use POST requests with Pydantic
models to handle and validate data. We’ll use fun examples with names like Alusine, Hawa, and Valentine to
make it super clear and engaging!

What is a Request Body?


The request body is the data you send to your API in a POST request. It’s like filling out a form and submitting
it to the server.
Think of it like this :
A GET request is like asking, “Show me the list of students!”
A POST request is like saying, “Here’s a new student—add them to the list!”
The data is usually sent as JSON , which looks like:

{"name": "Alusine", "age": 21}

FastAPI uses Pydantic models to define what this data should look like and to ensure it’s correct.

What is Pydantic Again?


Pydantic is a Python library that helps you:
Define the structure of your data (e.g., a student must have a name and age).
Validate the data (e.g., ensure age is a number, not text).
Work seamlessly with FastAPI to keep your API safe and user-friendly.
We’ll use Pydantic to manage the request body in our POST requests.

Example 1: Adding a Student with POST


Let’s create an API that lets you add a new student, like Alusine, by sending their details.

Code:

Page 25 of 43
fastapi

from fastapi import FastAPI


from pydantic import BaseModel

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

Use Swagger UI (easiest way):


Go to http://127.0.0.1:8000/docs .
Find the /students/ POST endpoint, click “Try it out.”
Enter this JSON:

{"name": "Alusine", "age": 21, "grade": 88.5}

Click “Execute.” You’ll see:

Page 26 of 43
fastapi

{"message": "Student created", "data": {"name": "Alusine", "age": 21, "grade": 88.5}}

Try with curl (if you prefer the terminal):


curl -X POST "http://127.0.0.1:8000/students/" -H "Content-Type: application/json" -d '{"name":
"Alusine", "age": 21, "grade": 88.5}'

What If You Send Bad Data?


Try this in Swagger UI:

{"name": "Hawa", "age": "twenty"}

You’ll get an error:


{"detail": [{"loc": ["body", "age"], "msg": "Input should be a valid integer", "type":
"type_error.integer"}]}

Why? Pydantic caught that age isn’t a number.

Why It’s Cool:


Pydantic ensures the data is correct before your code runs, preventing errors!

Example 2: Creating a Book with Required and Optional Fields


Let’s make an API to add a book, using Hawa as the author, with some optional fields.

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}}

Try without in_stock :

{"title": "Python Mastery", "author": "Hawa", "price": 19.99}

It still works, using the default in_stock: true .

Why It’s Cool:


Optional fields make your API flexible, and Pydantic handles it effortlessly!

Example 3: Nested Data (A Student with Courses)


Let’s create an API for a student, like Valentine, who has a list of courses.

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 bad data:


{
"name": "Valentine",
"age": 22,
"courses": [
{"name": "Biology", "credits": "three"}
]
}

Pydantic will catch that credits should be a number, not text.

Why It’s Cool:


Pydantic can validate complex, nested data, making your API powerful and reliable!
Page 29 of 43
fastapi

Key Points to Remember


POST Requests : Used to send data to your API (like adding a new student).
Request Body : The data (usually JSON) sent in a POST request.
Pydantic Models : Define the structure of the data and validate it.
FastAPI + Pydantic : Automatically checks the data and converts it to a Python object.
Testing : Use Swagger UI ( /docs ) or tools like Postman or curl to send POST requests.

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.

Controlling API Responses in FastAPI


In FastAPI, you can control exactly what your API sends back to the user, ensuring the output is
clear, consistent, and matches a specific structure. This is done using Pydantic models with the
response_model parameter. This guide will make it super easy to understand how to control
responses, using examples with names like Kubra, Moore, and Osman to keep it engaging and
relatable for students!

What Are API Responses?


An API response is what your API sends back when someone makes a request (like visiting a URL or sending
data). It’s usually in JSON format, like:

{"name": "Kubra", "age": 79}

With FastAPI, you can use response_model to:


Define the structure of the response (e.g., it must have a name and age).
Ensure the output matches that structure, even if your code returns extra data.
Make your API’s documentation (Swagger UI) clearer.

Why Control Responses?


Controlling responses is important because:
1. Consistency : Users know exactly what to expect from your API.
Page 30 of 43
fastapi
2. Safety : You can hide extra data you don’t want to share.
3. Better Docs : The Swagger UI ( /docs ) shows the exact response structure.
4. Validation : Pydantic checks that the response matches the model.

Example 1: Getting a Student by ID


Let’s create an API that returns a student’s details, like Kubra’s, and uses response_model to control the output.

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:

uvicorn main:app --reload

Visit: http://127.0.0.1:8000/students/42
You’ll see:
Page 31 of 43
fastapi

{"name": "Kubra", "age": 79, "grade": 92.5}

Check Swagger UI ( http://127.0.0.1:8000/docs ):


The /students/{student_id} endpoint will show that it returns a Student model with name ,
age , and grade .

Why It’s Cool:


The response_model ensures the output is exactly what you defined, and Swagger UI shows this structure
clearly!

Example 2: Filtering Extra Data


Sometimes, your function might return extra data you don’t want to send. response_model can filter it out.

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}

Notice: The secret_info field is not included!

Why It’s Cool:


response_model keeps your API clean by only sending the data you want, hiding sensitive or unnecessary
fields.
Page 32 of 43
fastapi

Example 3: Using Response Model with POST


You can also use response_model with POST requests to control what’s returned after sending data.

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:

{"name": "Osman", "age": 21, "grade": 90.5}

You’ll get:

{"name": "Osman", "age": 21, "message": "Welcome, Osman!"}

The grade field is excluded because it’s not in StudentOutput .

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!

Example 4: Nested Response Model


Let’s return a student with a list of courses, using a nested Pydantic model.

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}
]
}

Why It’s Cool:


response_model handles complex, nested data and keeps the output clean!

Key Points to Remember


Responses : What your API sends back (usually JSON).
Response Model : Use response_model=YourModel to define the output structure.
Pydantic : Validates and filters the response to match the model.
Benefits : Consistency, safety, and clearer documentation.
Flexibility : Works with GET, POST, and complex data like lists or nested models.

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 .

Hands-On Exercise: Build a To-Do List API with FastAPI


Let’s put everything we’ve learned about FastAPI into action by building a To-Do List API ! This will be a fun,
hands-on project where you create an API to manage a to-do list. You’ll learn how to list tasks, add new tasks,
and test your API—all in a way that’s super clear and easy to understand. Think of it like building a digital sticky
note app!

What You’ll Build


Your To-Do List API will have two main features:
1. GET /todos/ : List all tasks (with optional skip and limit query parameters to control how many
tasks you see).
Page 35 of 43
fastapi
2. POST /todos/ : Add a new task using a Pydantic model to ensure the data is correct.
We’ll use Pydantic for data validation and store tasks in a simple list (like a notebook for your to-dos). You’ll test
it using FastAPI’s awesome Swagger UI or a tool like Postman.

Step 1: Understand the Starter Code


Here’s the code to get you started. It’s simple but powerful!

from fastapi import FastAPI


from pydantic import BaseModel

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.

Step 2: Set Up and Run the API


Let’s get this code running!
1. Save the Code :
Copy the code above into a file called main.py .
2. Run the API :
Open your terminal (Command Prompt on Windows, Terminal on macOS/Linux).
Make sure you’re in the folder with main.py .
Run this command:

uvicorn main:app --reload

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:

INFO: Uvicorn running on http://127.0.0.1:8000

3. Check It’s Working :


Open your browser and go to http://127.0.0.1:8000/docs .
You’ll see Swagger UI, a cool interface to test your API!

Step 3: Test the POST Route (Add a Task)


Let’s add some to-do tasks using the POST route.

Using Swagger UI:


1. Go to http://127.0.0.1:8000/docs .
2. Find the POST /todos/ endpoint (it’ll say “POST” next to it).
3. Click “Try it out.”
4. In the Request body box, enter this JSON:
{"task": "Finish math homework", "completed": false}

5. Click “Execute.”
6. You’ll see the response:
Page 37 of 43
fastapi

{
"message": "Todo added",
"todo": {
"task": "Finish math homework",
"completed": false
}
}

Try Adding More Tasks:


Add another task:

{"task": "Read history book", "completed": false}

Try one that’s already done:

{"task": "Clean room", "completed": true}

What If You Send Bad Data?


Try this in Swagger UI:
{"task": "Study", "completed": "yes"}

You’ll get an error:


{"detail": [{"loc": ["body", "completed"], "msg": "Input should be a valid boolean", "type":
"type_error.boolean"}]}

Why? Pydantic checked that completed must be true or false , not text.

Why It’s Cool:


Your API is storing tasks in the todos list, and Pydantic makes sure the data is correct!

Step 4: Test the GET Route (List Tasks)


Now let’s check the tasks you added using the GET route.

Using Swagger UI:


1. In http://127.0.0.1:8000/docs , find the GET /todos/ endpoint.
2. Click “Try it out.”
3. Leave the skip and limit fields as they are (defaults: skip=0 , limit=10 ).
4. Click “Execute.”
5. You’ll see something like:

Page 38 of 43
fastapi

[
{"task": "Finish math homework", "completed": false},
{"task": "Read history book", "completed": false},
{"task": "Clean room", "completed": true}
]

Play with Query Parameters:


Try skip=1 and limit=2 :
Visit: http://127.0.0.1:8000/todos/?skip=1&limit=2
Or in Swagger UI, set skip to 1 and limit to 2.
You’ll see:
[
{"task": "Read history book", "completed": false},
{"task": "Clean room", "completed": true}
]

Why? It skips the first task and shows only two.

Why It’s Cool:


The skip and limit query parameters let you control which tasks to show, like flipping through pages in a
notebook!

Step 5: Test with Postman (Optional)


If you want to try a tool like Postman (a popular app for testing APIs):
1. Open Postman and create a new request.
2. For POST:
Set the method to POST and URL to http://127.0.0.1:8000/todos/ .
Go to the “Body” tab, select “raw” and “JSON.”
Enter:
{"task": "Buy groceries", "completed": false}

Click “Send.” You’ll see the response.


3. For GET:
Set the method to GET and URL to http://127.0.0.1:8000/todos/?skip=0&limit=10 .
Click “Send.” You’ll see the list of tasks.
Swagger UI is easier for beginners, but Postman is great for practice!

Page 39 of 43
fastapi

Step 6: Challenge Yourself!


Try these to make your API even better:
1. Add a New Field :
Update the Todo model to include a priority: int = 1 (e.g., 1 for low, 5 for high).
Test adding a task like:
{"task": "Study for exam", "completed": false, "priority": 5}

2. Filter Completed Tasks :


Modify the GET route to include a query parameter completed: bool = None .
If completed=true , only show completed tasks. Example:

@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]

Test with: http://127.0.0.1:8000/todos/?completed=true .


3. Clear the List :
Add a DELETE route to clear all tasks:
@app.delete("/todos/")
def clear_todos():
todos.clear()
return {"message": "All todos cleared"}

Key Points to Remember


GET /todos/ : Lists tasks with skip and limit to control the output.
POST /todos/ : Adds a new task using a Pydantic model.
Pydantic : Ensures tasks have a task (string) and completed (boolean).
Testing : Use Swagger UI ( /docs ) or Postman to try your API.
Storage : The todos list holds your tasks (it resets when you restart the app).

Why This is Awesome


You just built a real API that can manage a to-do list! This is like creating the backend for a to-do app someone
could use on their phone. You’ve learned routes, query parameters, Pydantic models, and how to test your API—
all in one project!

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!

FastAPI Take-Home Assignment: Build a Library API


Objective : Create a FastAPI application to manage books in a library system, practicing routes, path parameters,
query parameters, Pydantic models, request bodies, and response control.

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}}

Task 2: List Books (GET)


Endpoint : GET /books/
Description : List books with optional filtering.
Requirements :
Support query parameters: skip: int = 0 , limit: int = 10 , author: str = None (filter by
author).
Return matching books.
Example Request : /books/?skip=1&limit=2&author=Hawa
Example Response :

Page 41 of 43
fastapi

[{"title": "FastAPI Guide", "author": "Hawa", "price": 19.99, "in_stock": true}]

Task 3: Get a Book by ID (GET)


Endpoint : GET /books/{book_id}
Description : Retrieve a book by its ID (index in books list).
Requirements :
Use path parameter book_id: int .
Use response_model=Book .
Return 404 error for invalid ID.
Example Request : /books/0
Example Response :

{"title": "Python Programming", "author": "Alusine", "price": 29.99, "in_stock": true}

Task 4: Update a Book (PUT)


Endpoint : PUT /books/{book_id}
Description : Update a book’s details by ID.
Requirements :
Use path parameter book_id: int .
Accept Book model in request body.
Update book in books list.
Return updated book with message.
Return 404 for invalid ID.
Example Request Body :
{"title": "Advanced Python", "author": "Valentine", "price": 39.99, "in_stock": false}

Example Response :
{"message": "Book updated", "book": {"title": "Advanced Python", "author": "Valentine", "price":
39.99, "in_stock": false}}

Optional Challenges (Extra Credit)


1. DELETE Endpoint : Create DELETE /books/{book_id} to remove a book, return {"message": "Book
deleted"} , handle invalid IDs.
2. Categor y Field : Add category: str = None to Book model, filter by category in GET /books/ .
3. Nested Model : Add Review model ( rating: int , comment: str ), include reviews: List[Review]
= [] in Book , allow reviews in POST/PUT.
Page 42 of 43
fastapi

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.

created with the evaluation version of Markdown Monster

Page 43 of 43

You might also like