# FastAPI מאפס: התקנה, app = FastAPI(), Route ראשון והרצת השרת<no value>

## מה נלמד?

השיעור הזה הוא **הקמה מלאה, מאפס**, של שרת אמיתי:

1. **סביבה וירטואלית** (venv): איפה מתקינים ספריות.
2. **התקנת FastAPI** עם `pip`.
3. **`main.py`**: ייבוא, יצירת `app`, ו-**Route** ראשון.
4. **הרצה** עם `uvicorn`.
5. **בדיקה**: דפדפן, curl, ודף התיעוד האוטומטי `/docs`.

## למה צריך את זה?

בנושא מחשב, מערכת הפעלה ורשת כתבנו שרת "ידני" עם `socket`: `bind`, `listen`, `accept`, ופענוח של טקסט. ראינו כמה עבודה זה, וכמה קל לקרוס על קלט רע. **FastAPI** עושה את כל זה בשבילנו: מקבל את הבקשה, מפענח HTTP, מוצא את הפונקציה הנכונה, ממיר את התשובה ל-JSON, ובודק טיפוסים. אנחנו כותבים **רק את הלוגיקה**.

FastAPI היא מהספריות הנפוצות ביותר ל-Backend ב-Python, בעיקר ב-APIs ובעולמות ה-Data וה-AI.

## הסבר מהבסיס

### מהו FastAPI?

**FastAPI** היא **Framework** (מסגרת עבודה) לבניית Web APIs ב-Python. Framework = ספרייה שמכתיבה **מבנה**: "אתה כותב פונקציות, ואני קורא להן כשמגיעה בקשה מתאימה".

**Uvicorn** הוא **שרת ה-HTTP** עצמו: התוכנה שמאזינה על פורט (נושא מחשב, מערכת הפעלה ורשת: `listen`), מקבלת חיבורים, ומעבירה כל בקשה ל-FastAPI. FastAPI = **מה** לענות. Uvicorn = **הקבלה** בכניסה.

```text
Browser ──HTTP──► Uvicorn (listens on port 8000) ──► FastAPI (finds the right function) ──► your function
        ◄──JSON── Uvicorn ◄── FastAPI (converts dict to JSON) ◄──────────────────────── return {...}
```

### ספרייה חיצונית ו-pip

עד עכשיו השתמשנו רק במודולים **שמגיעים עם Python** (`os`, `json`, `logging`). FastAPI היא **ספרייה חיצונית** (Third-party Package), ולכן צריך להתקין אותה.

**pip** הוא מנהל החבילות של Python: מוריד ספריות מ-**PyPI** (מאגר הספריות הציבורי של Python) ומתקין אותן.

### סביבה וירטואלית (venv) — ולמה צריך אותה

אם מתקינים ספריות "גלובלית" (לכל המחשב), פרויקט אחד צריך FastAPI בגרסה 0.100, ופרויקט אחר צריך 0.142, ויש התנגשות. **Virtual Environment** (venv) = **תיקייה פרטית לפרויקט**, עם עותק משלה של Python ושל הספריות שלו. כל פרויקט עם הספריות שלו, בלי התנגשויות.

{{< box "analogy" "אנלוגיה: ארגז כלים לכל פרויקט" >}}
שיפוצניק שעובד על שלושה בתים לא מחזיק את כל הכלים בערימה אחת בבית. לכל אתר עבודה יש **ארגז כלים משלו**, עם בדיוק מה שהאתר צריך. venv = ארגז הכלים של הפרויקט. ו"הפעלה" (activate) = "אני עובד עכשיו עם הארגז **הזה**".
{{< /box >}}

### Decorator — `@app.get("/")`

שורה שמתחילה ב-`@` מעל `def` היא **Decorator** (ראינו `@property` בנושא OOP). ב-FastAPI, `@app.get("/")` אומר: **"רשום את הפונקציה שמתחת כמטפלת בבקשות `GET` לנתיב `/`"**.

זוכרים את המחשבון מנושא Python, עם dict של פונקציות (`OPERATIONS = {"+": add, ...}`)? FastAPI בונה בדיוק טבלה כזו: **(Method, Path) ‏←‏ פונקציה**. כל `@app.get(...)` מוסיף שורה לטבלה. כשמגיעה בקשה, FastAPI מחפש בטבלה וקורא לפונקציה. (זה Functions as Objects בפעולה!)

**Route** (מסלול) = הקישור בין Endpoint (Method + Path) לבין הפונקציה שמטפלת בו.

## תחביר

### שלב 1 — תיקייה וסביבה וירטואלית

```powershell
mkdir ~\dev\kodkod6\week-4\hello-api
cd ~\dev\kodkod6\week-4\hello-api
python -m venv .venv
```

### שלב 2 — הפעלת הסביבה

**Windows (PowerShell):**

```powershell
.venv\Scripts\Activate.ps1
```

**Mac / Linux:**

```bash
source .venv/bin/activate
```

ה-Prompt משתנה ומתחיל ב-`(.venv)`. **מעכשיו `python` ו-`pip` הם של הפרויקט.**

### שלב 3 — התקנה

```powershell
pip install "fastapi[standard]"
```

`[standard]` מתקין את FastAPI **יחד עם** Uvicorn ועוד כמה כלים שימושיים. בדיקה:

```powershell
pip list
```

### שלב 4 — `main.py`

```python
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def home():
    return {"message": "Hello from my first server!"}
```

### שלב 5 — הרצה

```powershell
uvicorn main:app --reload
```

### שלב 6 — בדיקה

- דפדפן: `http://127.0.0.1:8000/`
- תיעוד: `http://127.0.0.1:8000/docs`
- עצירה: `Ctrl + C`

## דוגמת קוד ראשונה

אחרי שלבים 1–5, ה-Terminal מציג:

```text
INFO:     Will watch for changes in these directories: ['C:\\Users\\dana\\dev\\kodkod6\\week-4\\hello-api']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [43864] using StatReload
INFO:     Started server process [29224]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
```

בדפדפן, `http://127.0.0.1:8000/`:

```json
{"message":"Hello from my first server!"}
```

וב-Terminal נוספת שורה על הבקשה:

```text
INFO:     127.0.0.1:52311 - "GET / HTTP/1.1" 200 OK
```

## פירוק הקוד שורה אחר שורה

**`main.py`:**

| שורה | הסבר |
|---|---|
| `from fastapi import FastAPI` | מייבא את ה-**Class** בשם `FastAPI` מתוך הספרייה (נושא Python: `from ... import`). |
| `app = FastAPI()` | יוצר **אובייקט** מה-Class (נושא OOP!). `app` הוא **האפליקציה**: הוא מחזיק את טבלת ה-Routes, ו-Uvicorn ידבר איתו. |
| `@app.get("/")` | Decorator: "רשום את `home` כמטפלת ב-`GET /`". `get` היא **מתודה** של האובייקט `app`. |
| `def home():` | פונקציה רגילה. השם חופשי. FastAPI מזהה אותה לפי ה-Decorator, ולא לפי השם. |
| `return {"message": "..."}` | מחזירים **dict**, ו-FastAPI ממיר אותו ל-**JSON** אוטומטית (Serialization, נושא Python) ומחזיר Status 200. |

**הפקודה `uvicorn main:app --reload`:**

| חלק | הסבר |
|---|---|
| `uvicorn` | הפעלת שרת ה-HTTP. |
| `main` | **המודול**: הקובץ `main.py` (בלי `.py`). |
| `:app` | **האובייקט** בתוך המודול: המשתנה `app`. "תריץ את האפליקציה שנקראת `app`, שנמצאת ב-`main`". |
| `--reload` | **מצב פיתוח**: כששומרים שינוי בקוד, השרת מאתחל את עצמו אוטומטית. **רק לפיתוח**, לא בשרת אמיתי. |

**שורות הפלט:**

| שורה | משמעות (וחיבור לנושא מחשב, מערכת הפעלה ורשת) |
|---|---|
| `Will watch for changes...` | מצב `--reload`: מעקב אחרי קבצים בתיקייה. |
| `Uvicorn running on http://127.0.0.1:8000` | השרת **מאזין** (`listen`) על **localhost**, **פורט 8000**. |
| `Started reloader process [43864]` | תהליך "שומר" שמזהה שינויים. **PID**. |
| `Started server process [29224]` | **התהליך** שבאמת מטפל בבקשות. PID נוסף. |
| `"GET / HTTP/1.1" 200 OK` | **לוג** של כל בקשה: Method, Path, גרסה ו-Status Code. |

## דוגמה נוספת

**עוד Routes, ו-`/docs`.** עדכנו את `main.py` (עם `--reload`, השרת מתעדכן לבד ברגע שתשמרו):

```python
from fastapi import FastAPI

app = FastAPI(title="Kodkod Hello API")

COURSE = {"name": "Kodkod 6", "weeks": 5, "topics": ["OS", "Python", "OOP", "Backend", "DB"]}


@app.get("/")
def home():
    return {"message": "Hello from my first server!"}


@app.get("/course")
def course_info():
    return COURSE


@app.get("/course/topics")
def course_topics():
    return COURSE["topics"]


@app.get("/health")
def health():
    return {"status": "ok"}
```

**בדיקות עם curl** (ב-Terminal **נוסף**, כי הראשון תפוס בשרת):

```powershell
curl.exe http://127.0.0.1:8000/course
curl.exe http://127.0.0.1:8000/course/topics
curl.exe -i http://127.0.0.1:8000/nothing
```

**פלט:**

```text
{"name":"Kodkod 6","weeks":5,"topics":["OS","Python","OOP","Backend","DB"]}
["OS","Python","OOP","Backend","DB"]
HTTP/1.1 404 Not Found
date: Tue, 06 Oct 2026 14:30:00 GMT
server: uvicorn
content-length: 22
content-type: application/json

{"detail":"Not Found"}
```

**פירוק:**

- `FastAPI(title="Kodkod Hello API")` — שם לאפליקציה, שיופיע בדף התיעוד.
- **אפשר להחזיר כל מה ש-JSON יודע לייצג**: dict (`/course`), **רשימה** (`/course/topics`), מחרוזת או מספר.
- **נתיב שלא הוגדר** (`/nothing`): FastAPI מחזיר לבד **404**, עם JSON של שגיאה. לא כתבנו לזה שורה אחת.
- `/health` — Endpoint מקובל בשרתים אמיתיים: מערכות ניטור בודקות אותו כל כמה שניות, כדי לדעת שהשרת חי.

### `/docs` — התיעוד האוטומטי

פתחו `http://127.0.0.1:8000/docs`. FastAPI **בנה לבד** דף תיעוד אינטראקטיבי (נקרא **Swagger UI**):

- רשימה של **כל ה-Endpoints**, עם Method ו-Path.
- לחיצה על Endpoint → **Try it out** → **Execute**: שולח בקשה אמיתית ומציג את התשובה.
- התיעוד מתעדכן אוטומטית עם כל Route חדש.

בנושא Students API – שרת עם מסד נתונים נשתמש בו כ**כלי הבדיקה המרכזי** של השרת.

## טעות נפוצה

**הטעות 1: להתקין בלי להפעיל את ה-venv**, או לפתוח Terminal חדש ולשכוח להפעיל אותו.

```text
uvicorn : The term 'uvicorn' is not recognized ...
```

או:

```text
ModuleNotFoundError: No module named 'fastapi'
```

**בדיקה:** האם ה-Prompt מתחיל ב-`(.venv)`? אם לא, `.venv\Scripts\Activate.ps1`. **בכל Terminal חדש מפעילים מחדש.** (חלופה שתמיד עובדת: `python -m uvicorn main:app --reload`.)

**הטעות 2: ב-Windows, הפעלה נחסמת.**

```text
.venv\Scripts\Activate.ps1 cannot be loaded because running scripts is disabled on this system.
```

PowerShell חוסם הרצת סקריפטים כברירת מחדל. פותחים PowerShell ומריצים **פעם אחת**:

```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```

(זה מתיר סקריפטים מקומיים למשתמש שלכם בלבד. נושא מחשב, מערכת הפעלה ורשת: הרשאות!)

**הטעות 3: `main:app` לא תואם לקוד.**

```text
ERROR:    Error loading ASGI app. Attribute "app" not found in module "main".
```

הקובץ לא נקרא `main.py`, או שהמשתנה לא נקרא `app` (למשל `application = FastAPI()`). הפורמט הוא תמיד `<file>:<variable>`. ומריצים **מהתיקייה שבה הקובץ נמצא** (Current Working Directory, נושא מחשב, מערכת הפעלה ורשת!).

**הטעות 4: פורט תפוס.**

```text
ERROR:    [WinError 10048] error while attempting to bind on address ('127.0.0.1', 8000): only one usage of each socket address (protocol/network address/port) is normally permitted
```

שרת אחר (או עותק קודם של אותו שרת) כבר מאזין על 8000 (נושא מחשב, מערכת הפעלה ורשת!). עוצרים אותו עם `Ctrl + C` ב-Terminal שלו, או מריצים על פורט אחר: `uvicorn main:app --reload --port 8001`.

**הטעות 5: להכניס את `.venv` ל-Git.** התיקייה ענקית ומכילה אלפי קבצים, שתלויים במחשב שלכם. מוסיפים ל-`.gitignore`:

```text
.venv/
__pycache__/
```

ובמקום זה, שומרים **רשימה** של הספריות: `pip freeze > requirements.txt`. מי שמוריד את הפרויקט מריץ `pip install -r requirements.txt`.

<!-- exercises:start — generated by scripts/intro6/sync_site_exercises.py; edit scripts/intro6/exercises/ -->
## תרגול

התרגילים מבוססים רק על מה שנלמד בשיעור הזה ובשיעורים שלפניו. נסו לבד, ורק אז פתחו את הפתרון.

### תרגיל 1: הקמת פרויקט

כתבו את רצף הפקודות שמקים פרויקט `hello-api`: תיקייה, סביבה וירטואלית, הפעלה שלה (Windows), והתקנת FastAPI. מה התפקיד של הסביבה הווירטואלית?

{{< solution >}}
```powershell
mkdir hello-api
cd hello-api
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install "fastapi[standard]"
pip list
```

(ב-Mac: `source .venv/bin/activate`.)

**סביבה וירטואלית (venv)** מבודדת את החבילות של הפרויקט: כל פרויקט עם הגרסאות שלו, בלי להתנגש בפרויקטים אחרים או ב-Python של המחשב. את התיקייה `.venv` לא מכניסים ל-Git.
{{< /solution >}}

### תרגיל 2: Route ראשון

כתבו `main.py` עם אפליקציית FastAPI ו-Route ל-`/` שמחזיר `{"message": "Hello from my first server!"}`. איך מריצים, ולאיזו כתובת גולשים?

{{< solution >}}
```python
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def home():
    return {"message": "Hello from my first server!"}
```

מריצים:

```powershell
uvicorn main:app --reload
```

וגולשים ל-`http://127.0.0.1:8000`. `main:app` = הקובץ `main.py`, המשתנה `app`. `--reload` מפעיל מחדש את השרת אחרי כל שמירה.
{{< /solution >}}

### תרגיל 3: מבקשה לפונקציה

סדרו את המסלול של בקשה, מהדפדפן ועד הפונקציה שלנו וחזרה:

- (א) FastAPI ממיר את ה-dict ל-JSON
- (ב) הדפדפן שולח `GET /`
- (ג) הפונקציה `home()` מחזירה dict
- (ד) Uvicorn מקבל את הבקשה בפורט 8000
- (ה) FastAPI מוצא את הפונקציה שמתאימה ל-`GET /`

{{< solution >}}
הסדר: **(ב), (ד), (ה), (ג), (א)**

1. הדפדפן שולח `GET /`.
2. **Uvicorn** — השרת עצמו — מקבל את הבקשה בפורט 8000.
3. **FastAPI** מוצא את ה-Route שמתאים ל-Method ולנתיב.
4. הפונקציה שלנו מחזירה **dict** רגיל.
5. FastAPI ממיר אותו ל-**JSON** ומחזיר תשובה עם 200.
{{< /solution >}}

### תרגיל 4: Quotes API

כתבו API של ציטוטים עם רשימת ציטוטים (מילונים עם `text` ו-`author`), ושני Routes:

- `GET /quotes` — כל הציטוטים;
- `GET /quotes/count` — `{"count": <number>}`.

תנו לאפליקציה כותרת `"Quotes API"`.

{{< solution >}}
```python
from fastapi import FastAPI

app = FastAPI(title="Quotes API")

QUOTES = [
    {"text": "Simple is better than complex.", "author": "The Zen of Python"},
    {"text": "Readability counts.", "author": "The Zen of Python"},
    {"text": "Talk is cheap. Show me the code.", "author": "Linus Torvalds"},
]


@app.get("/quotes")
def all_quotes():
    return QUOTES


@app.get("/quotes/count")
def count_quotes():
    return {"count": len(QUOTES)}
```

`GET /quotes/count` מחזיר `{"count": 3}`. FastAPI ממיר גם רשימה ל-JSON. הכותרת מופיעה בדף התיעוד ב-`/docs`.
{{< /solution >}}

### תרגיל 5: Swagger UI

1. מה יש בכתובת `http://127.0.0.1:8000/docs`?
2. איך משתמשים בו כדי לבדוק Route?

{{< solution >}}
1. **Swagger UI** — דף תיעוד ש-FastAPI בונה **אוטומטית** מהקוד: כל ה-Routes, ה-Method של כל אחד, הפרמטרים והתשובות.
2. פותחים Route, לוחצים **Try it out**, ממלאים פרמטרים אם יש, ולוחצים **Execute**. רואים את הבקשה שנשלחה, את ה-Status Code ואת גוף התשובה — בלי לכתוב Client.
{{< /solution >}}

<!-- exercises:end -->

## סיכום

- **FastAPI** = Framework שמגדירים בו Routes. **Uvicorn** = שרת ה-HTTP שמאזין על הפורט ומעביר בקשות ל-FastAPI.
- **venv**: `python -m venv .venv`, הפעלה (`Activate.ps1` / `source .venv/bin/activate`), ואז `pip install "fastapi[standard]"`. בכל Terminal חדש מפעילים מחדש.
- `app = FastAPI()` = אובייקט האפליקציה. **`@app.get("/path")`** רושם פונקציה כמטפלת ב-`GET /path`.
- מחזירים dict או list, ו-FastAPI ממיר ל-JSON עם 200. נתיב לא קיים מקבל 404 אוטומטית.
- הרצה: **`uvicorn main:app --reload`** (`קובץ:משתנה`), מהתיקייה של הקובץ. עצירה: `Ctrl + C`.
- **`/docs`** = תיעוד ובדיקה אינטראקטיביים, אוטומטיים.
- `.venv/` ב-`.gitignore`. `requirements.txt` ב-Git.

<!-- docs:start — generated by scripts/intro6/site_docs.py; edit the links there -->

## דוקומנטציה רשמית

- [FastAPI — Virtual Environments](https://fastapi.tiangolo.com/virtual-environments/) — venv והתקנה
- [FastAPI — First Steps](https://fastapi.tiangolo.com/tutorial/first-steps/) — app = FastAPI() ו-Route ראשון
- [FastAPI — Interactive API docs](https://fastapi.tiangolo.com/tutorial/first-steps/#interactive-api-docs) — Swagger UI ב-/docs

<!-- docs:end -->
