FastAPI
✕Introduction to FastAPI
- Modern, high-performance web framework for building APIs with Python.
- External Library. Installed as:
pip install fastapi[standard] - Start Server as:
fastapi dev main.py - Web Application: A software application that runs on a web server and is accessed through a web browser or API client.
- Web Framework: A software framework that provides tools and libraries to build web applications and APIs. E.g:
FastAPI,Django,Flasketc. - API (Application Programming Interface): A set of rules that allows different software applications to communicate with each other.
Terminologies:
Typical API Terminologies
- Endpoint: A URL route that performs a specific function (e.g.
/students). - HTTP Methods: Actions performed on endpoints.
GET,POST,PUT,DELETE. - Request Body: Data sent by the client to the server.
JSON payload. - Response: Data sent back to client after processing a request by server.
- Status Codes: Codes indicating result of a request. Eg.
200,404 Not Found. - Query Parameters: Key-value pairs in the URL used for filtering or additional info. E.g:
/students?age=20 - Path Parameters: Dynamic segments in the URL that capture values. E.g:
/students/{student_id}
Basic FastAPI Example
from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"}# Run with:fastapi dev main.py
Helper Functions for Database Interaction
- Define helper functions to interact with the database.
- This abstracts away database logic from endpoint definitions.
import sqlite3 con = sqlite3.connect("students.db") cur = con.cursor() def run_query(sql_query, type="SELECT"): cursor = con.cursor() cursor.execute(sql_query) if type == "SELECT": return cursor.fetchall()
Example:
Creating GET Endpoint
- Used to retrieve data from the server.
- Data is sent back in the response body.
@app.get("/students") def get_students_endpoint(): students = run_query("SELECT * FROM students") return {"students": students}@app.get("/students/{student_id}") def get_student(student_id: int): student = run_query(f"SELECT * FROM students WHERE id={student_id}") if student: return {"student": student[0]} else: return {"error": "Student not found"}@app.get("/students/search/") def search_students(age: int = None, name: str = None): query = "SELECT * FROM students WHERE 1=1" if age: query = query + f" AND age={age}" if name: query = query + f" AND name LIKE '%{name}%'" students = run_query(query) return {"students": students}
Example:
Using GET Endpoint with Query Parameters
- Query parameters are used to filter information in GET requests.
- They are included in the URL after
?and are in the form of key-value pairs. import requests url ="http://localhost:8000/students/search/"params = {"age": 20, "name": "John"} response = requests.get(url, params=params)# params is optionaldata = response.json() print(data)
Example:
Creating POST Endpoint
- Used to submit data to the server.
- Data is sent in the request body.
@app.post("/students") def add_student(student: dict): sql_query = f"""INSERT INTO students (name, age) VALUES ('{student['name']}', {student['age']})""" run_query(sql_query, type="INSERT") return {"message": "Student added successfully"}import requests url ="http://localhost:8000/students"student_data = {"name": "Alice", "age": 22} response = requests.post(url, json=student_data) data = response.json() print(data)params = {"name": "Alice", "age": 22} response = requests.get("http://localhost:8000/students",params=params) data = response.json() print(data)
Example:
Testing POST Endpoint with Python Client
Validating with GET
Creating PUT Endpoint
- Used to update existing data on the server.
- Data is sent in the request body.
@app.put("/students/{student_id}") def update_student(student_id: int, student: dict): sql_query = f"""UPDATE students SET name='{student['name']}', age={student['age']} WHERE id={student_id}""" run_query(sql_query, type="UPDATE") return {"message": "Student updated successfully"}import requests url ="http://localhost:8000/students/1"updated_data = {"name": "Alice Smith", "age": 23} response = requests.put(url, json=updated_data) data = response.json() print(data)response = requests.get("http://localhost:8000/students/1")data = response.json() print(data)
Example:
Testing PUT Endpoint with Python Client
Validating with GET
Creating DELETE Endpoint
- Used to delete existing data on the server.
@app.delete("/students/{student_id}") def delete_student(student_id: int): sql_query = f"""DELETE FROM students WHERE id={student_id}""" run_query(sql_query, type="DELETE") return {"message": "Student deleted successfully"}import requests url ="http://localhost:8000/students/1"response = requests.delete(url) data = response.json() print(data)response = requests.get("http://localhost:8000/students/1")data = response.json() print(data)
Example:
Testing DELETE Endpoint with Python Client
Validating with GET
HTTP Status Codes
- Indicate the result of a client's request to the server.
- Specified in the response sent by the server.
- Range:
100 - 599, first digit indicates category of response. -1xx: Informational -2xx: Success -3xx: Redirection -4xx: Client Error -5xx: Server Error
Common Status Codes and Their Meanings
Common HTTP Status Codes:
| Status Code | Meaning | Use Case |
|---|---|---|
| 200 OK | Request was successful. | General success response. |
| 201 Created | Resource was successfully created. | Successful POST request. |
| 204 No Content | Request was successful but no content to return. | Successful DELETE request. |
| 400 Bad Request | Client sent an invalid request. | Malformed request syntax or invalid data. |
| 404 Not Found | Requested resource does not exist. | Resource not found at the specified URL. |
| 500 Internal Server Error | Server encountered an error processing the request. | Unexpected server error. |
Common HTTP status codes used in API responses.
Concept of Asynchronous Endpoint
- Allow the server to handle multiple requests concurrently without blocking.
- Implemented using
async defandawaitin FastAPI. - Useful for I/O-bound operations like database queries or external API calls.
- Analogy: Chef boiling pasta while preparing sauce, instead of waiting.

Demo Code for Synchronous Endpoint
def get_data_from_site(name): print(f"Start fetching {name}") time.sleep(3) # simulating network delay print(f"Finished fetching {name}") return f"Data from {name}" @app.get("/sync") def sync_demo(): result1 = get_data_from_site("Site A") result2 = get_data_from_site("Site B") return {"results": [result1, result2]}
Demo Code for Asynchronous Endpoint
import asyncio async def get_data_from_site(name): print(f"Start fetching {name}") await asyncio.sleep(3) # simulating network delay print(f"Finished fetching {name}") return f"Data from {name}" @app.get("/async") async def async_endpoint(): task1 = asyncio.create_task(get_data_from_site("Site A")) task2 = asyncio.create_task(get_data_from_site("Site B")) result1 = await task1 result2 = await task2 return {"results": [result1, result2]}
