A RESTful API for managing patient records, built with FastAPI and Pydantic. It supports full CRUD operations, sorting, strict input validation, and automatically computes each patient's BMI and health verdict using Pydantic computed fields.
Manage patient records through a clean REST API — create, view, update, delete, and sort patients — with BMI and a health verdict derived automatically from height and weight.
POST a patient (with height & weight)
↓
Pydantic validates the input, then computes BMI and a verdict
↓
Record is saved and returned
- Full CRUD — create, view, update, and delete patient records
- Automatic BMI computation — calculated from height and weight via Pydantic's
@computed_field, so it's never stored incorrectly or out of sync - Health verdict — each patient is categorized (Underweight / Normal / Obese) based on their BMI
- Sorting — sort patients by height, weight, or BMI, in ascending or descending order
- Strict validation — Pydantic enforces rules: age must be between 0 and 120, height and weight must be positive, gender is restricted to valid options
- Partial updates — a dedicated update model lets clients change only the fields they want; BMI and verdict are automatically recalculated
- Proper error handling — returns clear HTTP errors (404 for missing patients, 400 for invalid input/duplicates)
- Interactive API docs — auto-generated Swagger UI at
/docs
FastAPI · Pydantic · Uvicorn · Python · JSON file storage
Each patient record contains:
| Field | Type | Rules |
|---|---|---|
id |
string | Required (e.g. P001) |
name |
string | Required |
city |
string | Required |
age |
integer | Required, 0 < age < 120 |
gender |
male / female / others | Required, restricted values |
height |
float | Required, > 0 (in meters) |
weight |
float | Required, > 0 (in kg) |
bmi |
float | Computed automatically |
verdict |
string | Computed automatically from BMI |
| Method | Endpoint | What it does |
|---|---|---|
GET |
/ |
Welcome message |
GET |
/about |
API description |
GET |
/view |
List all patients |
GET |
/patient/{patient_id} |
Get a single patient by ID |
GET |
/sort?sort_by=bmi&order=desc |
Sort patients by height, weight, or BMI |
POST |
/create |
Add a new patient (BMI + verdict computed automatically) |
PUT |
/edit/{patient_id} |
Update a patient (partial updates; BMI recalculated) |
DELETE |
/delete/{patient_id} |
Remove a patient |
# 1. Install dependencies
pip install fastapi uvicorn
# 2. Start the server
uvicorn main:app --reloadThen open http://localhost:8000/docs for interactive documentation, where you can try every endpoint directly in the browser.
Note: the API reads and writes to a
patients.jsonfile in the same folder, so make sure that file exists (it can start as{}).
Rather than storing BMI as a plain field that could drift out of sync, this API uses Pydantic's @computed_field to derive BMI from height and weight every time:
@computed_field
@property
def bmi(self) -> float:
return round(self.weight / (self.height ** 2), 2)
@computed_field
@property
def verdict(self) -> str:
if self.bmi < 18.5:
return 'underweight'
elif self.bmi < 25:
return 'Normal'
...This means BMI and verdict are always consistent with the current height and weight — update a patient's weight and both recompute automatically. It's a clean example of derived data done right.
The PatientUpdate model makes every field optional, so a client can send just the fields they want to change:
- Load the existing patient
- Apply only the provided fields (
exclude_unset=Trueignores fields the client didn't send) - Rebuild the patient as a full
Patientobject — which recomputes BMI and verdict with the new values - Save
So updating just the weight automatically refreshes the BMI and verdict too.
- Building a complete REST API with FastAPI (routing, path and query parameters, request bodies, status codes)
- Data modeling and validation with Pydantic (field constraints, restricted values, optional fields for partial updates)
- Computed fields — deriving values (BMI, verdict) from inputs so they stay consistent
- Proper HTTP error handling (404, 400, 201)
- Auto-generated interactive API documentation
Patient data is persisted in a patients.json file for simplicity. In a production system this would be a database — the API and validation layers would stay the same, only the storage functions (load_data / save_data) would change.