Yaliyomo

Wiki 9: Jinsi Web Inavyofanya Kazi, requests, na Utangulizi wa FastAPI

Mwezi 3 | Lengo kuu: Mwanafunzi aelewe client/server na HTTP, atumie requests kuongea na API ya umma, kisha ajenge API yake ya kwanza kwa FastAPI.


Maandalizi ya Mwalimu (soma kabla ya wiki kuanza)

  1. Soma:
  2. Jaribu mwenyewe kabla ya darasa — andika code YOTE ya Kipindi 1–3 kwenye kompyuta yako ya kufundishia (ile unayo-share screen). Usiingie darasani bila kuona output kwa macho yako.
  3. Andaa folda kwenye kompyuta ya kufundishia:

    powershell
    cd $HOME\Documents
    mkdir wiki09
    cd wiki09
    python -m venv .venv
    .\.venv\Scripts\Activate.ps1
    pip install requests "fastapi[standard]"
    

    Ukipata error running scripts is disabled on this system, endesha mara moja: Set-ExecutionPolicy -Scope CurrentUser RemoteSigned kisha jibu Y.

  4. Hakikisha internet inafanya kazi na unaweza kufungua https://jsonplaceholder.typicode.com/todos/1 kwenye browser. Hii ndiyo "API ya umma" tutakayotumia — ni ya bure, haihitaji akaunti wala key.

  5. VS Code extensions: Python (Microsoft). Hiari: "Thunder Client" au "REST Client" — lakini wiki hii tutatumia browser, /docs ya FastAPI, na requests, hivyo hazihitajiki.
  6. Maneno muhimu ya kukumbuka (andika kwenye karatasi pembeni): client, server, request, response, URL, endpoint, path, query string, method (GET/POST/PUT/PATCH/DELETE), status code, header, body, JSON, API.

Malengo ya Wiki (mwisho wa wiki mwanafunzi ataweza...)

  1. Kueleza kwa maneno yake client na server ni nini, na request/response ni nini.
  2. Kuvunja URL katika sehemu zake: scheme, host, port, path, query string.
  3. Kutaja HTTP methods 5 kuu na kazi yake (GET, POST, PUT, PATCH, DELETE).
  4. Kutambua makundi ya status codes (2xx, 3xx, 4xx, 5xx) na codes muhimu: 200, 201, 204, 400, 401, 403, 404, 422, 500.
  5. Kutumia requests kufanya GET na POST, kutuma query parameters, kusoma JSON, na kushughulikia errors (timeout, status mbaya).
  6. Kusakinisha FastAPI na kuendesha server kwa fastapi dev main.py.
  7. Kuandika endpoints zenye path parameters na query parameters zenye type hints.
  8. Kutumia /docs (Swagger UI) kujaribu API yake.

Kipindi 1 — Jinsi Web Inavyofanya Kazi: Client, Server, HTTP

Mtiririko wa kipindi

  1. Marudio ya kazi ya nyumbani ya Wiki 8 (Git/GitHub) — mwanafunzi aonyeshe repo yake
  2. Picha kubwa: client na server, request na response (analogy ya mgahawa)
  3. URL inavyoundwa: scheme, host, port, path, query
  4. HTTP methods na status codes
  5. JSON ni nini na kwa nini API zinaitumia; kufungua API kwenye browser
  6. DevTools ya browser: kuona requests halisi (Network tab)
  7. Zoezi darasani
  8. Q&A + kazi ya nyumbani

Elezo kwa mwalimu (soma kwanza wewe)

Client na server. Kompyuta mbili (au programu mbili) zinaongea. Moja inaomba kitu — hiyo ni client (mfano browser, app ya simu, script ya Python). Nyingine inasubiri maombi na kujibu — hiyo ni server (programu inayoendeshwa mahali fulani, inasikiliza kwenye "port").

Request na response. Mazungumzo yote ya web ni jozi: client anatuma request, server anarudisha response. Hakuna response bila request. Server haiwezi "kumpigia" client yenyewe kwa HTTP ya kawaida.

HTTP ni "lugha" (protocol) wanayotumia. Request ya HTTP ina sehemu hizi:

  • Method — kitendo: GET (soma), POST (unda kipya), PUT (badilisha kizima), PATCH (badilisha sehemu), DELETE (futa).
  • URL — anwani ya kitu unachotaka.
  • Headers — taarifa za ziada (mfano Content-Type: application/json, Authorization: Bearer ...).
  • Body — data unayotuma (kwa kawaida kwenye POST/PUT/PATCH). GET haina body kwa kawaida.

Response ina:

  • Status code — namba ya matokeo (200 = sawa, 404 = haipo...).
  • Headers — mfano Content-Type: application/json.
  • Body — data yenyewe (HTML kwa ukurasa wa web, JSON kwa API).

URL mfano: https://jsonplaceholder.typicode.com:443/posts?userId=1&_limit=5

  • https — scheme (http ni bila usimbaji fiche; https ni salama/encrypted)
  • jsonplaceholder.typicode.com — host (jina la server)
  • 443 — port (kwa https ni 443 kwa default, ndiyo maana huwa haiandikwi; http ni 80; server yetu ya FastAPI itakuwa 8000)
  • /posts — path (rasilimali/kitu gani)
  • ?userId=1&_limit=5 — query string (vichujio/filters, jozi za key=value zilizotenganishwa na &)

Endpoint = mchanganyiko wa method + path, mfano GET /posts au POST /posts. Hizi ni endpoints mbili TOFAUTI ingawa path ni moja.

API (Application Programming Interface) — kwa web, ni seti ya endpoints ambazo programu nyingine zinaweza kuziita, na mara nyingi zinarudisha JSON badala ya HTML. Website ni kwa binadamu; API ni kwa programu.

JSON — tayari mwanafunzi anaijua kutoka wiki ya files (module json). Hapa msisitize: JSON ni maandishi (text) yanayofanana na dict/list ya Python. API zinaitumia kwa sababu kila lugha (JavaScript, Python, Java...) inaweza kuisoma.

Status codes — makundi:

  • 1xx — taarifa (hatuzitumii sana)
  • 2xx — mafanikio: 200 OK, 201 Created, 204 No Content
  • 3xx — redirect (nenda mahali pengine): 301, 302, 304
  • 4xx — kosa la CLIENT (wewe umekosea): 400 Bad Request, 401 Unauthorized (hujaingia/login), 403 Forbidden (umeingia lakini huna ruhusa), 404 Not Found, 405 Method Not Allowed, 422 Unprocessable Entity (data haijakaa sawa — FastAPI inaitumia sana)
  • 5xx — kosa la SERVER: 500 Internal Server Error, 503 Service Unavailable

Kanuni rahisi: 4 = "kosa lako", 5 = "kosa langu (server)".

Stateless. HTTP haikumbuki request iliyopita. Kila request inajitegemea. Ndiyo maana baadaye (Wiki 11) tutatuma "token" kwenye kila request ili server ijue sisi ni nani.

Sema hivi kwa mwanafunzi

"Fikiria uko mgahawani. Wewe ni client. Jikoni ni server. Mhudumu ni HTTP — ndiye anayebeba ujumbe. Unaagiza: 'Naomba chipsi mayai' — hiyo ni request. Mhudumu analeta sahani — hiyo ni response. Kama chipsi zimekwisha, mhudumu anasema 'Samahani, hazipo' — hiyo ni 404 Not Found. Kama jiko limeungua moto, ni 500 — kosa si lako, ni la jikoni."

"Menyu ya mgahawa ndiyo API — inakuambia vitu gani unaweza kuagiza na jinsi ya kuviagiza. Huwezi kuingia jikoni mwenyewe; unapitia menyu na mhudumu."

"Methods ni vitenzi: GET = 'nipe/nionyeshe', POST = 'unda/ongeza', PUT = 'badilisha chote', PATCH = 'rekebisha kidogo', DELETE = 'futa'. Kama tuna daftari la wanafunzi: kusoma orodha ni GET, kuandikisha mwanafunzi mpya ni POST, kubadilisha namba ya simu tu ni PATCH, kumtoa ni DELETE."

"URL ni kama anwani ya posta: https ni aina ya usafiri (gari lenye kufuli), host ni jina la jengo, port ni namba ya mlango, path ni chumba gani, na query string ni maelezo ya ziada — 'nipe faili za mwaka 2026 tu'."

Andika code hii live (share screen)

Hatua 1 — Fungua API kwenye browser. Andika kwenye browser:

text
https://jsonplaceholder.typicode.com/todos/1

Output inayotarajiwa (browser inaonyesha JSON):

json
{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

Sema: "Hii ni response ya API. Si ukurasa mzuri wa HTML — ni data tupu kwa ajili ya programu."

Jaribu pia:

  • https://jsonplaceholder.typicode.com/users/1 — mtumiaji mmoja
  • https://jsonplaceholder.typicode.com/posts?userId=1 — posts za user 1 tu (query string!)
  • https://jsonplaceholder.typicode.com/todos/99999 — utapata {} na status 404

Hatua 2 — DevTools. Bonyeza F12 kwenye Chrome/Edge → tab ya Network → refresh (F5). Bonyeza request ya 1 (todos/1). Mwonyeshe:

  • Headers → Request URL, Request Method: GET, Status Code: 200
  • Response Headers → content-type: application/json; charset=utf-8
  • Response → JSON yenyewe

Kisha fungua todos/99999 na uonyeshe Status Code: 404.

Hatua 3 — Request kutoka PowerShell (kuonyesha kwamba browser si lazima). Kwenye terminal ya VS Code:

powershell
Invoke-RestMethod https://jsonplaceholder.typicode.com/todos/1

Output:

text
userId id title              completed
------ -- -----              ---------
     1  1 delectus aut autem     False

Au kwa curl.exe (kumbuka .exe — kwenye Windows PowerShell 5.1, curl peke yake ni jina bandia la Invoke-WebRequest):

powershell
curl.exe -i https://jsonplaceholder.typicode.com/todos/1

-i inaonyesha headers. Mwonyeshe mstari wa kwanza: HTTP/1.1 200 OK (au HTTP/2 200).

Hatua 4 — JSON na Python (marudio). Unda json_marudio.py:

python
import json

maandishi = '{"jina": "Amina", "umri": 21, "masomo": ["Python", "Git"], "ameandikishwa": true}'

data = json.loads(maandishi)       # text -> dict
print(type(data))                  # <class 'dict'>
print(data["masomo"][0])           # Python
print(data["ameandikishwa"])       # True  (JSON true -> Python True)

nyuma = json.dumps(data, ensure_ascii=False)  # dict -> text
print(type(nyuma))                 # <class 'str'>
print(nyuma)

Output:

text
<class 'dict'>
Python
True
<class 'str'>
{"jina": "Amina", "umri": 21, "masomo": ["Python", "Git"], "ameandikishwa": true}

Sisitiza tofauti: JSON true/false/null ↔ Python True/False/None. JSON inatumia double quotes " tu.

Hatua 5 — Kuvunja URL kwa Python (inaonyesha sehemu za URL kwa uwazi):

python
from urllib.parse import urlparse, parse_qs

url = "https://jsonplaceholder.typicode.com:443/posts?userId=1&_limit=5"
sehemu = urlparse(url)

print("scheme:", sehemu.scheme)
print("host:  ", sehemu.hostname)
print("port:  ", sehemu.port)
print("path:  ", sehemu.path)
print("query: ", sehemu.query)
print("query kama dict:", parse_qs(sehemu.query))

Output:

text
scheme: https
host:   jsonplaceholder.typicode.com
port:   443
path:   /posts
query:  userId=1&_limit=5
query kama dict: {'userId': ['1'], '_limit': ['5']}

Angalia: values za query daima ni text ('1' si 1). FastAPI itatugeuzia kuwa int baadaye kwa kutumia type hints.

Maswali ya kumuuliza mwanafunzi

  1. Browser yako ni client au server? — Client.
  2. Ukifungua YouTube kwenye simu, nani ni client na nani ni server? — App ya YouTube kwenye simu ni client; kompyuta za Google ni server.
  3. GET /posts na POST /posts ni endpoint moja? — Hapana, ni mbili tofauti; method ni sehemu ya endpoint.
  4. Status 404 maana yake nini, na ni kosa la nani? — Haipatikani; kundi la 4xx ni kosa la client (umeomba kitu kisichokuwepo).
  5. Tofauti ya 401 na 403? — 401: server haikujui (hujaingia/login). 403: inakujua lakini huna ruhusa.
  6. Kwenye https://shop.co.tz/bidhaa?aina=simu&bei_max=500000, path ni nini na query ni nini? — Path: /bidhaa. Query: aina=simu&bei_max=500000.
  7. Kwa nini API zinatumia JSON badala ya HTML? — JSON ni data tupu iliyopangwa, rahisi kwa programu yoyote (lugha yoyote) kusoma; HTML ni kwa kuonyesha kwa binadamu.
  8. Ukitaka kubadilisha namba ya simu tu ya mteja, utatumia method gani? — PATCH (au PUT kama unatuma mteja mzima).
  9. HTTP "stateless" maana yake nini? — Kila request inajitegemea; server haikumbuki request iliyopita yenyewe.

Makosa ya kawaida

Kosa Ujumbe / dalili Suluhisho
Kutumia curl badala ya curl.exe kwenye Windows PowerShell 5.1 Cannot process command because of one or more missing mandatory parameters: Uri. (au PowerShell inaomba Uri) Andika curl.exe
Kuchanganya / na ? URL .../posts/userId=1 inarudisha 404 Query inaanza na ?: /posts?userId=1
Kutenganisha query kwa , au ? mara mbili ?userId=1?_limit=5 haifanyi kazi sawa Tumia &: ?userId=1&_limit=5
JSON yenye single quotes json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes JSON inakubali " tu
Kuandika True ndani ya JSON text JSONDecodeError: Expecting value Ndani ya JSON tumia true, false, null
Kudhani query values ni namba parse_qs inarudisha ['1'] Geuza kwa int(...) (FastAPI itafanya hili yenyewe)

Zoezi darasani

Zoezi 1.1 — Kwa kila URL, taja scheme, host, path, na query (kwa mdomo au kwa maandishi):

  • a) http://127.0.0.1:8000/items/5?q=simu
  • b) https://api.github.com/users/octocat/repos?per_page=3

Zoezi 1.2 — Linganisha kitendo na method + status code inayofaa:

  • a) Kuomba orodha ya bidhaa → ?
  • b) Kuunda akaunti mpya kwa mafanikio → ?
  • c) Kuomba bidhaa yenye id ambayo haipo → ?
  • d) Kufuta bidhaa kwa mafanikio bila kurudisha data → ?
  • e) Kutuma fomu yenye umri = "kumi" badala ya namba → ?

Zoezi 1.3 — Fungua kwenye browser https://jsonplaceholder.typicode.com/comments?postId=1. Tumia DevTools (Network) kusema: status code, content-type, na comments ngapi zimerudi (hesabu kwenye JSON).

Zoezi 1.4 — Andika script url_vunja.py inayomwomba mtumiaji URL kwa input(), kisha inachapisha host, path, na kila query parameter kwenye mstari wake.

Jibu

1.1

  • a) scheme http, host 127.0.0.1 (port 8000), path /items/5, query q=simu
  • b) scheme https, host api.github.com, path /users/octocat/repos, query per_page=3

1.2

  • a) GET → 200 OK
  • b) POST → 201 Created
  • c) GET → 404 Not Found
  • d) DELETE → 204 No Content
  • e) POST → 422 Unprocessable Entity (au 400 Bad Request)

1.3 Status 200, content-type: application/json; charset=utf-8, comments 5.

1.4

python
from urllib.parse import urlparse, parse_qs

url = input("Weka URL: ")
sehemu = urlparse(url)

print("Host:", sehemu.hostname)
print("Path:", sehemu.path)

query = parse_qs(sehemu.query)
if not query:
    print("Hakuna query parameters.")
for key, values in query.items():
    print(f"  {key} = {values[0]}")

Mfano:

text
Weka URL: https://shop.co.tz/bidhaa?aina=simu&bei_max=500000
Host: shop.co.tz
Path: /bidhaa
  aina = simu
  bei_max = 500000

Kipindi 2 — Kuongea na API kwa requests

Mtiririko wa kipindi

  1. Marudio ya kazi ya nyumbani (maswali ya HTTP / script ya URL)
  2. Kusakinisha requests ndani ya venv; kwa nini si urllib
  3. requests.get: status_code, headers, .json(), params=
  4. requests.post kwa json=; kusoma 201
  5. Errors: timeout, raise_for_status(), ConnectionError
  6. Mini-project: pakua todos, chuja, hifadhi kwenye faili JSON
  7. Zoezi darasani
  8. Q&A + kazi ya nyumbani

Elezo kwa mwalimu (soma kwanza wewe)

requests ni library maarufu ya Python ya kutuma HTTP requests. Python ina urllib ndani yake, lakini requests ni rahisi zaidi kusoma na kuandika.

Muhimu kujua:

  • requests.get(url) inarudisha object ya Response.
  • response.status_code → namba (mfano 200).
  • response.ok → True kama status iko chini ya 400.
  • response.headers → dict-like ya headers.
  • response.text → body kama string.
  • response.json() → body imegeuzwa kuwa dict/list ya Python (inafanya json.loads kwa niaba yako). Ikiwa body si JSON, itarusha error.
  • params={"userId": 1} → requests inajenga query string yenyewe (?userId=1). Usiunganishe strings mwenyewe.
  • json={"title": "..."} kwenye POST → requests inageuza dict kuwa JSON na kuweka header Content-Type: application/json.
  • timeout=10 → usisubiri milele. Daima weka timeout. Bila timeout, script inaweza kuganda.
  • response.raise_for_status() → kama status ni 4xx au 5xx, inarusha requests.HTTPError. Ikiwa ni sawa, haifanyi kitu.
  • Exceptions muhimu (zote ni watoto wa requests.RequestException): requests.ConnectionError (hakuna internet / server haipo), requests.Timeout, requests.HTTPError.

Kumbuka: JSONPlaceholder ni API ya "bandia" — POST inarudisha 201 na kitu chenye id: 101, lakini haihifadhi kweli. Mweleze mwanafunzi hili ili asishangae kwamba GET /posts/101 inarudisha 404.

Sema hivi kwa mwanafunzi

"Kipindi kilichopita tulitumia browser kama client. Leo Python yetu itakuwa client. requests ni kama kumpa script yako simu ya kupiga server."

"params= ni kama kumwambia mhudumu 'chipsi, lakini bila pilipili' — hayo ni maelezo ya ziada (query). json= ni kama kumpa mhudumu barua iliyoandikwa — hiyo ni body."

"timeout ni uvumilivu wako. Ukipiga simu na haipokelewi kwa sekunde 10, unakata. Bila timeout, script itasubiri milele kama mtu aliyesahau simu sikioni."

"raise_for_status() ni kama mlinzi: kama jibu ni baya (4xx/5xx), anapiga kelele (exception) mara moja badala ya kukuacha uendelee na data mbovu."

Andika code hii live (share screen)

Hatua 1 — Sakinisha. Kwenye terminal (venv iwe active — angalia (.venv) mwanzoni mwa mstari):

powershell
pip install requests
pip show requests

Hatua 2 — GET ya kwanza. Unda api_1.py:

python
import requests

url = "https://jsonplaceholder.typicode.com/todos/1"
response = requests.get(url, timeout=10)

print("Status:", response.status_code)
print("OK?:", response.ok)
print("Content-Type:", response.headers["Content-Type"])
print("Text:", response.text[:60], "...")

data = response.json()
print(type(data))
print("Title:", data["title"])
print("Imekamilika?:", data["completed"])

Output:

text
Status: 200
OK?: True
Content-Type: application/json; charset=utf-8
Text: {
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem", ...
<class 'dict'>
Title: delectus aut autem
Imekamilika?: False

Hatua 3 — List na params. Unda api_2.py:

python
import requests

BASE = "https://jsonplaceholder.typicode.com"

response = requests.get(f"{BASE}/todos", params={"userId": 1}, timeout=10)
print("URL iliyotumwa:", response.url)

todos = response.json()
print(type(todos), "idadi:", len(todos))

zilizokamilika = [t for t in todos if t["completed"]]
print("Zilizokamilika:", len(zilizokamilika))

for t in todos[:3]:
    alama = "✔" if t["completed"] else "✘"
    print(f"{alama} {t['id']}: {t['title']}")

Output:

text
URL iliyotumwa: https://jsonplaceholder.typicode.com/todos?userId=1
<class 'list'> idadi: 20
Zilizokamilika: 11
✘ 1: delectus aut autem
✘ 2: quis ut nam facilis et officia qui
✘ 3: fugiat veniam minus

Sisitiza: response.url inaonyesha requests ilijenga ?userId=1 yenyewe.

Kama terminal inaonyesha alama za ajabu badala ya ✔/✘, badilisha kuwa "[x]" na "[ ]". (Windows Terminal ya kisasa inazionyesha vizuri.)

Hatua 4 — POST. Unda api_3.py:

python
import requests

post_mpya = {
    "title": "Habari kutoka Dar",
    "body": "Najifunza requests leo.",
    "userId": 1,
}

response = requests.post(
    "https://jsonplaceholder.typicode.com/posts",
    json=post_mpya,
    timeout=10,
)

print("Status:", response.status_code)
print(response.json())

Output:

text
Status: 201
{'title': 'Habari kutoka Dar', 'body': 'Najifunza requests leo.', 'userId': 1, 'id': 101}

Eleza: 201 Created — server inasema "nimeunda". id: 101 ni id mpya iliyotolewa na server (bandia hapa).

Hatua 5 — Kushughulikia errors. Unda api_4.py:

python
import requests

def pata_user(user_id: int) -> dict | None:
    url = f"https://jsonplaceholder.typicode.com/users/{user_id}"
    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()
    except requests.HTTPError as e:
        print(f"Kosa la HTTP: {e.response.status_code}")
        return None
    except requests.ConnectionError:
        print("Hakuna mtandao au server haipatikani.")
        return None
    except requests.Timeout:
        print("Server imechelewa sana.")
        return None
    return response.json()


user = pata_user(1)
if user:
    print(user["name"], "-", user["email"], "-", user["address"]["city"])

pata_user(999)

Output:

text
Leanne Graham - Sincere@april.biz - Gwenborough
Kosa la HTTP: 404

Kisha zima Wi-Fi (au badilisha URL kuwa https://haipo-kabisa-12345.com) na uendeshe tena — onyesha Hakuna mtandao au server haipatikani. Hii inafanya somo likumbukwe.

Hatua 6 — Mini-project: pakua na hifadhi. Unda hifadhi_todos.py:

python
import json
from pathlib import Path

import requests

BASE = "https://jsonplaceholder.typicode.com"


def pakua_todos(user_id: int) -> list[dict]:
    r = requests.get(f"{BASE}/todos", params={"userId": user_id}, timeout=10)
    r.raise_for_status()
    return r.json()


def main() -> None:
    todos = pakua_todos(2)
    hazijakamilika = [
        {"id": t["id"], "title": t["title"]}
        for t in todos
        if not t["completed"]
    ]
    faili = Path("todos_user2.json")
    faili.write_text(json.dumps(hazijakamilika, indent=2), encoding="utf-8")
    print(f"Nimehifadhi todos {len(hazijakamilika)} kwenye {faili}")


if __name__ == "__main__":
    main()

Output:

text
Nimehifadhi todos 12 kwenye todos_user2.json

Fungua todos_user2.json ndani ya VS Code umwonyeshe.

Maswali ya kumuuliza mwanafunzi

  1. response.json() inarudisha nini kwa /todos/1 na kwa /todos? — Ya kwanza dict, ya pili list (ya dicts).
  2. Kwa nini tunatumia params={...} badala ya kuandika ?userId=1 kwenye string? — Requests inajenga na ku-encode query vizuri (nafasi, alama maalum), na code inasomeka zaidi.
  3. Tofauti ya json= na params=? — params inaenda kwenye URL (query string); json inaenda kwenye body.
  4. Usipoweka timeout kuna hatari gani? — Script inaweza kusubiri milele server isipojibu.
  5. raise_for_status() inafanya nini kwenye status 200? — Hakuna kitu; inarusha error kwa 4xx/5xx tu.
  6. Kwa nini GET /posts/101 ni 404 baada ya POST kufanikiwa? — JSONPlaceholder ni API bandia; haihifadhi data.
  7. requests.get(...) ikifanikiwa lakini status ni 404, je exception inarushwa? — Hapana! Isipokuwa ukiita raise_for_status(). Ndiyo maana tunaiita.

Makosa ya kawaida

Kosa Ujumbe / dalili Suluhisho
requests haijasakinishwa au venv si active ModuleNotFoundError: No module named 'requests' Activate venv (.\.venv\Scripts\Activate.ps1), pip install requests; VS Code: chagua interpreter ya .venv (Ctrl+Shift+P → "Python: Select Interpreter")
Kuita faili requests.py AttributeError: partially initialized module 'requests' has no attribute 'get' (most likely due to a circular import) Badilisha jina la faili, futa folda __pycache__
Kusahau () kwenye .json Unapata <bound method Response.json of <Response [200]>> response.json()
Kuita .json() kwenye response isiyo JSON requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0) Angalia status_code na headers["Content-Type"] kwanza
Kuandika data= badala ya json= Server inapokea form data, si JSON; API nyingi zinarudisha 400/422 Tumia json=dict kwa API za JSON
t.completed badala ya t["completed"] AttributeError: 'dict' object has no attribute 'completed' JSON → dict; tumia mabano [...]
Kuweka timeout kwenye string ValueError timeout=10 (namba)

Zoezi darasani

Zoezi 2.1 — Andika script inayopakua https://jsonplaceholder.typicode.com/users na kuchapisha jina na mji (address.city) wa kila mtumiaji.

Zoezi 2.2 — Andika function posts_za(user_id: int) -> int inayorudisha idadi ya posts za mtumiaji huyo (tumia params). Ijaribu kwa user 1 na 5.

Zoezi 2.3 — Andika function tengeneza_todo(title: str) -> dict inayotuma POST /todos yenye {"title": title, "completed": False, "userId": 1} na kurudisha JSON ya response. Hakikisha status ni 201 kwa kutumia raise_for_status() na assert.

Zoezi 2.4 (changamoto) — Hesabu ni mtumiaji gani (userId) ana todos nyingi zaidi zilizokamilika. Tumia request MOJA tu (/todos).

Jibu

2.1

python
import requests

r = requests.get("https://jsonplaceholder.typicode.com/users", timeout=10)
r.raise_for_status()
for u in r.json():
    print(f"{u['name']:<25} {u['address']['city']}")

Output (mistari 10; mwanzo):

text
Leanne Graham             Gwenborough
Ervin Howell              Wisokyburgh
Clementine Bauch          McKenziehaven
...

2.2

python
import requests

def posts_za(user_id: int) -> int:
    r = requests.get(
        "https://jsonplaceholder.typicode.com/posts",
        params={"userId": user_id},
        timeout=10,
    )
    r.raise_for_status()
    return len(r.json())

print(posts_za(1))  # 10
print(posts_za(5))  # 10

2.3

python
import requests

def tengeneza_todo(title: str) -> dict:
    r = requests.post(
        "https://jsonplaceholder.typicode.com/todos",
        json={"title": title, "completed": False, "userId": 1},
        timeout=10,
    )
    r.raise_for_status()
    assert r.status_code == 201, r.status_code
    return r.json()

print(tengeneza_todo("Kununua sukari"))
# {'title': 'Kununua sukari', 'completed': False, 'userId': 1, 'id': 201}

2.4

python
from collections import Counter
import requests

r = requests.get("https://jsonplaceholder.typicode.com/todos", timeout=10)
r.raise_for_status()

hesabu = Counter(t["userId"] for t in r.json() if t["completed"])
user_id, idadi = hesabu.most_common(1)[0]
print(f"User {user_id} ana todos {idadi} zilizokamilika")
print(hesabu)

Output (mstari wa kwanza): User 5 ana todos 12 zilizokamilika. Users 5 na 10 wamefungana kwa 12; most_common inarudisha aliyeonekana kwanza.


Kipindi 3 — FastAPI: API Yako ya Kwanza

Mtiririko wa kipindi

  1. Marudio ya kazi ya nyumbani (scripts za requests)
  2. FastAPI ni nini; sasa SISI ndio server
  3. Kusakinisha, main.py ya kwanza, fastapi dev main.py
  4. /docs na /redoc — documentation ya bure
  5. Path parameters zenye types; 422 ikiwa type si sahihi
  6. Query parameters: default, optional (None), bool
  7. Kuita API yetu wenyewe kwa requests
  8. Zoezi darasani
  9. Q&A + kazi ya nyumbani

Elezo kwa mwalimu (soma kwanza wewe)

FastAPI ni framework ya Python ya kujenga APIs. Inatumia type hints (ambazo mwanafunzi anazijua kutoka Wiki 7) kufanya mambo matatu kwa niaba yetu:

  1. Kugeuza data (conversion) — "5" kutoka URL inakuwa 5 (int).
  2. Kuthibitisha data (validation) — "abc" kwa int inarudisha 422 na maelezo.
  3. Documentation — /docs inajengwa yenyewe.

Uvicorn ni server (ASGI server) inayoendesha app ya FastAPI. pip install "fastapi[standard]" inasakinisha FastAPI pamoja na uvicorn, fastapi CLI, httpx, python-multipart, na zaidi. Alama za nukuu "..." ni muhimu kwenye PowerShell kwa sababu ya mabano [ ].

fastapi dev main.py — inaendesha server kwa "development mode": inajiwasha upya (auto-reload) kila unapohifadhi faili. Inasikiliza http://127.0.0.1:8000. Kwa production kuna fastapi run main.py (hatutaitumia sasa). Kusimamisha server: Ctrl+C kwenye terminal.

127.0.0.1 (au localhost) = "kompyuta hii hii". Kwa hiyo client (browser) na server (FastAPI) wako kwenye kompyuta moja.

Decorator @app.get("/path") — mwanafunzi alijifunza decorators Wiki 8. Hapa decorator "inasajili" function: "request ya GET ikija kwenye /path, ita function hii". Function inarudisha dict/list → FastAPI inaigeuza kuwa JSON.

Path parameter: sehemu ya path inayobadilika, imeandikwa {jina}, na function inapokea argument yenye jina hilo hilo: @app.get("/items/{item_id}") → def read_item(item_id: int).

Query parameter: argument yoyote ya function ambayo HAIMO kwenye path inakuwa query parameter. Ikiwa na default → si lazima. Bila default → lazima (ukikosa unapata 422). q: str | None = None → si lazima, default None.

Bool kwenye query: FastAPI inakubali true/false, 1/0, yes/no, on/off.

Mpangilio wa routes (order) ni muhimu: FastAPI inakagua routes kwa mpangilio zilivyoandikwa. /users/me lazima iandikwe KABLA ya /users/{user_id}, la sivyo "me" itajaribiwa kama user_id na kutoa 422.

def au async def? Zote zinafanya kazi. Kwa kozi hii tutatumia def ya kawaida — ni rahisi na sahihi. async def ni kwa kazi za "await" (tutazitaja tu). Ukiulizwa: "FastAPI inaendesha def kwenye threadpool, hivyo haizuii server."

Sema hivi kwa mwanafunzi

"Mpaka sasa tumekuwa wateja mgahawani. Leo tunafungua mgahawa wetu! FastAPI ni jiko letu, na kila @app.get(...) ni chakula kipya kwenye menyu."

"Type hints ulizojifunza zamani zilikuwa 'maelezo tu' — Python haikuzijali. FastAPI inazichukulia kwa uzito: ukisema item_id: int, FastAPI itakataa 'abc' kwa niaba yako. Ni kama mlinzi getini anayekagua vitambulisho."

"/docs ni kama menyu ya kuchapishwa bure — umeandika code, na menyu imejitengeneza yenyewe, tena unaweza kuagiza moja kwa moja kutoka kwenye menyu (Try it out)."

"Path parameter ni 'nani/kipi' — /wanafunzi/7 = mwanafunzi namba 7. Query parameter ni 'vipi' — /wanafunzi?darasa=4&limit=10 = nionyeshe wa darasa la 4, kumi tu."

Andika code hii live (share screen)

Hatua 1 — Folda na usakinishaji.

powershell
cd $HOME\Documents
mkdir api_ya_kwanza
cd api_ya_kwanza
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install "fastapi[standard]"
code .

Hatua 2 — main.py ya kwanza:

python
from fastapi import FastAPI

app = FastAPI(title="API ya Kwanza")


@app.get("/")
def mwanzo():
    return {"ujumbe": "Karibu kwenye API yangu!"}

Endesha:

powershell
fastapi dev main.py

Output (sehemu muhimu):

text
 ⚡️ Starting FastAPI in development mode

 🐍 Using import string: main:app

 🌐 Server started at http://127.0.0.1:8000
    Documentation at http://127.0.0.1:8000/docs

  Logs:

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

(Mpangilio na mapambo ya maandishi haya hubadilika kati ya versions za FastAPI. Kilicho muhimu ni anwani ya server na Application startup complete.)

Fungua http://127.0.0.1:8000 kwenye browser:

json
{"ujumbe":"Karibu kwenye API yangu!"}

Angalia terminal — kuna mstari kama INFO: 127.0.0.1:52344 - "GET / HTTP/1.1" 200 OK. Sema: "Hiyo ni request ya browser ikifika kwenye server yetu. Sisi sasa ndio server!"

Hatua 3 — /docs. Fungua http://127.0.0.1:8000/docs. Bonyeza GET / → "Try it out" → "Execute". Mwonyeshe Response body na status 200. Kisha http://127.0.0.1:8000/redoc (mtindo mwingine). Pia http://127.0.0.1:8000/openapi.json — "hii ni maelezo ya API kwa mashine; /docs inajengwa kutoka hapa".

Hatua 4 — Data na path parameters. Badilisha main.py (server itajiwasha upya yenyewe ukihifadhi):

python
from fastapi import FastAPI

app = FastAPI(title="API ya Kwanza")

BIDHAA = {
    1: {"jina": "Sukari", "bei": 3000, "aina": "chakula"},
    2: {"jina": "Mchele", "bei": 2800, "aina": "chakula"},
    3: {"jina": "Sabuni", "bei": 1500, "aina": "usafi"},
    4: {"jina": "Daftari", "bei": 1000, "aina": "shule"},
    5: {"jina": "Kalamu", "bei": 500, "aina": "shule"},
}


@app.get("/")
def mwanzo():
    return {"ujumbe": "Karibu kwenye API yangu!"}


@app.get("/bidhaa/{bidhaa_id}")
def pata_bidhaa(bidhaa_id: int):
    if bidhaa_id not in BIDHAA:
        return {"kosa": "Bidhaa haipo"}
    return {"id": bidhaa_id, **BIDHAA[bidhaa_id]}

Jaribu kwenye browser:

  • http://127.0.0.1:8000/bidhaa/3 → {"id":3,"jina":"Sabuni","bei":1500,"aina":"usafi"}
  • http://127.0.0.1:8000/bidhaa/abc → 422:
json
{"detail":[{"type":"int_parsing","loc":["path","bidhaa_id"],"msg":"Input should be a valid integer, unable to parse string as an integer","input":"abc"}]}

Sema: "Hatukuandika if yoyote ya kukagua 'abc'. FastAPI imefanya yenyewe kwa sababu tuliandika int."

  • http://127.0.0.1:8000/bidhaa/99 → {"kosa":"Bidhaa haipo"} — lakini status ni 200! Mwonyeshe kwenye DevTools au /docs. Sema: "Hii si sahihi kabisa — tunapaswa kurudisha 404. Wiki ijayo tutajifunza HTTPException kurekebisha hili." (Hii ni ndoano nzuri ya Wiki 10.)

Hatua 5 — Query parameters. Ongeza:

python
@app.get("/bidhaa")
def orodha_bidhaa(aina: str | None = None, bei_max: int | None = None, limit: int = 10):
    matokeo = []
    for bid, b in BIDHAA.items():
        if aina is not None and b["aina"] != aina:
            continue
        if bei_max is not None and b["bei"] > bei_max:
            continue
        matokeo.append({"id": bid, **b})
    return matokeo[:limit]

Jaribu:

  • /bidhaa → bidhaa zote 5
  • /bidhaa?aina=shule → Daftari na Kalamu
  • /bidhaa?bei_max=2000&limit=2 → Sabuni na Daftari
  • /bidhaa?limit=kumi → 422 (int_parsing, loc: ["query","limit"])

Fungua /docs — onyesha kwamba aina, bei_max, limit zimeonekana kama query parameters, na limit ina default 10.

Hatua 6 — Route order (mtego). Ongeza CHINI ya /bidhaa/{bidhaa_id}:

python
@app.get("/bidhaa/nafuu")
def bidhaa_nafuu():
    return [b for b in BIDHAA.values() if b["bei"] <= 1000]

Fungua /bidhaa/nafuu → 422! Uliza: "Kwa nini?" Jibu: route ya /bidhaa/{bidhaa_id} imeandikwa juu, hivyo "nafuu" inajaribiwa kama bidhaa_id: int. Hamisha bidhaa_nafuu juu ya pata_bidhaa → sasa inafanya kazi:

json
[{"jina":"Daftari","bei":1000,"aina":"shule"},{"jina":"Kalamu","bei":500,"aina":"shule"}]

Hatua 7 — Required query na bool:

python
@app.get("/salamu")
def salamu(jina: str, rasmi: bool = False):
    if rasmi:
        return {"salamu": f"Shikamoo, {jina}."}
    return {"salamu": f"Mambo {jina}!"}
  • /salamu?jina=Juma → {"salamu":"Mambo Juma!"}
  • /salamu?jina=Bibi&rasmi=true → {"salamu":"Shikamoo, Bibi."}
  • /salamu → 422 "type":"missing","loc":["query","jina"],"msg":"Field required"

Hatua 8 — Kuita API yetu kwa requests. Server ikiwa bado inaendesha, fungua terminal ya pili (kitufe + kwenye terminal ya VS Code), activate venv, unda mteja.py:

python
import requests

BASE = "http://127.0.0.1:8000"

r = requests.get(f"{BASE}/bidhaa", params={"aina": "chakula"}, timeout=5)
print(r.status_code, r.json())

r = requests.get(f"{BASE}/salamu", params={"jina": "Neema", "rasmi": True}, timeout=5)
print(r.json()["salamu"])

Output:

text
200 [{'id': 1, 'jina': 'Sukari', 'bei': 3000, 'aina': 'chakula'}, {'id': 2, 'jina': 'Mchele', 'bei': 2800, 'aina': 'chakula'}]
Shikamoo, Neema.

Sema: "Sasa umeunganisha wiki nzima: Kipindi 1 (HTTP), Kipindi 2 (client), Kipindi 3 (server)."

Maswali ya kumuuliza mwanafunzi

  1. Kwa nini tunaandika "fastapi[standard]" kwa nukuu? — PowerShell inaweza kutafsiri mabano [ ]; nukuu zinahakikisha pip inapokea jina lote. [standard] inaleta uvicorn na zana nyingine.
  2. fastapi dev inafanya nini ukihifadhi faili? — Inajiwasha upya (reload) yenyewe.
  3. Ukiandika def pata(bidhaa_id: int) na path ni /bidhaa/{id}, nini kitatokea? — Majina hayalingani; FastAPI itachukulia bidhaa_id kama query parameter ya lazima, na id ya path haitumiki → 422 ukikosa ?bidhaa_id=. Majina lazima yafanane.
  4. Ni lini query parameter ni ya lazima? — Ikiwa haina default.
  5. Kwa nini /bidhaa/nafuu ilitoa 422 mwanzoni? — Route order: {bidhaa_id} ilikamata "nafuu" kwanza.
  6. Function inarudisha dict; client anapokea nini? — JSON (FastAPI inageuza).
  7. /bidhaa/99 ilirudisha status gani na ni sahihi? — 200; si sahihi, inapaswa kuwa 404 (tutarekebisha Wiki 10).
  8. 127.0.0.1 ni nini? — Kompyuta yako mwenyewe (localhost).

Makosa ya kawaida

Kosa Ujumbe / dalili Suluhisho
fastapi command haipatikani fastapi : The term 'fastapi' is not recognized... Venv haijawa active au haikusakinishwa: activate, pip install "fastapi[standard]"
Kusakinisha fastapi bila [standard] fastapi command haipo, au ujumbe unaosema To use the fastapi command, please install "fastapi[standard]" pip install "fastapi[standard]"
Port 8000 tayari inatumika (server nyingine bado inaendesha) ERROR: [Errno 10048] error while attempting to bind on address ('127.0.0.1', 8000) Simamisha server nyingine (Ctrl+C kwenye terminal yake) au fastapi dev main.py --port 8001
Kutokuwa na app = FastAPI() au kuiita jina lingine Could not find FastAPI app in module, try using --app Ita variable app, au fastapi dev main.py --app jina_lako
Jina la path param na argument kutofautiana 422 "loc":["query","bidhaa_id"],"msg":"Field required" {bidhaa_id} ↔ bidhaa_id: int
Route order 422 kwenye /bidhaa/nafuu Weka routes za path maalum juu ya zenye {param}
Kufungua https://127.0.0.1:8000 Browser: "This site can't provide a secure connection" Tumia http:// (si https) kwa local
mteja.py inaendeshwa wakati server imesimamishwa requests.exceptions.ConnectionError: ... [WinError 10061] No connection could be made because the target machine actively refused it Washa server kwanza kwenye terminal nyingine

Zoezi darasani

Zoezi 3.1 — Ongeza endpoint GET /kuhusu inayorudisha {"jina": "<jina lako>", "kozi": "Python", "wiki": 9}.

Zoezi 3.2 — Ongeza endpoint GET /hesabu/jumla/{a}/{b} inayorudisha {"a": a, "b": b, "jumla": a + b}. a na b ziwe float. Jaribu /hesabu/jumla/2.5/4.

Zoezi 3.3 — Ongeza endpoint GET /bidhaa/tafuta yenye query parameter ya lazima neno: str, inayorudisha bidhaa ambazo jina lake lina neno hilo (bila kujali herufi kubwa/ndogo). Mfano /bidhaa/tafuta?neno=SU → Sukari. (Kumbuka route order!)

Zoezi 3.4 — Ongeza query parameter panga: bool = False kwenye GET /bidhaa; ikiwa true, panga matokeo kwa bei (ndogo kwanza).

Jibu
python
from fastapi import FastAPI

app = FastAPI(title="API ya Kwanza")

BIDHAA = {
    1: {"jina": "Sukari", "bei": 3000, "aina": "chakula"},
    2: {"jina": "Mchele", "bei": 2800, "aina": "chakula"},
    3: {"jina": "Sabuni", "bei": 1500, "aina": "usafi"},
    4: {"jina": "Daftari", "bei": 1000, "aina": "shule"},
    5: {"jina": "Kalamu", "bei": 500, "aina": "shule"},
}


@app.get("/")
def mwanzo():
    return {"ujumbe": "Karibu kwenye API yangu!"}


# 3.1
@app.get("/kuhusu")
def kuhusu():
    return {"jina": "Amina", "kozi": "Python", "wiki": 9}


# 3.2
@app.get("/hesabu/jumla/{a}/{b}")
def jumla(a: float, b: float):
    return {"a": a, "b": b, "jumla": a + b}
# /hesabu/jumla/2.5/4 -> {"a":2.5,"b":4.0,"jumla":6.5}


# 3.4 (imeongezwa 'panga')
@app.get("/bidhaa")
def orodha_bidhaa(
    aina: str | None = None,
    bei_max: int | None = None,
    limit: int = 10,
    panga: bool = False,
):
    matokeo = [
        {"id": bid, **b}
        for bid, b in BIDHAA.items()
        if (aina is None or b["aina"] == aina)
        and (bei_max is None or b["bei"] <= bei_max)
    ]
    if panga:
        matokeo.sort(key=lambda b: b["bei"])
    return matokeo[:limit]


# 3.3 — LAZIMA iwe juu ya /bidhaa/{bidhaa_id}
@app.get("/bidhaa/tafuta")
def tafuta_bidhaa(neno: str):
    neno = neno.lower()
    return [
        {"id": bid, **b}
        for bid, b in BIDHAA.items()
        if neno in b["jina"].lower()
    ]
# /bidhaa/tafuta?neno=SU -> [{"id":1,"jina":"Sukari","bei":3000,"aina":"chakula"}]


@app.get("/bidhaa/{bidhaa_id}")
def pata_bidhaa(bidhaa_id: int):
    if bidhaa_id not in BIDHAA:
        return {"kosa": "Bidhaa haipo"}
    return {"id": bidhaa_id, **BIDHAA[bidhaa_id]}

/bidhaa?panga=true&limit=3 → Kalamu (500), Daftari (1000), Sabuni (1500).


Kazi ya Nyumbani

Kuwasilisha: kipindi kijacho.

Kazi A — "API ya Maktaba" (FastAPI). Unda main.py yenye list ya vitabu angalau 6 (kila kimoja: id, kichwa, mwandishi, mwaka, lugha — "sw" au "en"). Endpoints:

  1. GET / → ujumbe wa kukaribisha.
  2. GET /vitabu → query params: lugha: str | None = None, baada_ya: int | None = None (vitabu vya mwaka mkubwa kuliko huu), limit: int = 10.
  3. GET /vitabu/{kitabu_id} → kitabu kimoja; kama hakipo rudisha {"kosa": "Kitabu hakipo"}.
  4. GET /waandishi → list ya majina ya waandishi bila kurudia, yamepangwa kwa alfabeti.

Kazi B — Mteja (requests). Unda mteja.py inayoita API yako (server ikiwa inaendesha) na kuchapisha: (1) idadi ya vitabu vya Kiswahili, (2) kitabu namba 2, (3) orodha ya waandishi. Tumia timeout na raise_for_status().

Kazi C — Maswali (andika kwenye majibu.md):

  1. Eleza kwa maneno yako tofauti ya path parameter na query parameter, kwa mfano wako mwenyewe.
  2. Taja status codes 3 za kundi la 4xx na maana yake.
  3. Kwa nini GET /vitabu/99 yako inarudisha 200 ingawa kitabu hakipo, na ni status gani ingefaa?
Jibu

Kazi A — main.py

python
from fastapi import FastAPI

app = FastAPI(title="API ya Maktaba")

VITABU = [
    {"id": 1, "kichwa": "Kusadikika", "mwandishi": "Shaaban Robert", "mwaka": 1951, "lugha": "sw"},
    {"id": 2, "kichwa": "Rosa Mistika", "mwandishi": "Euphrase Kezilahabi", "mwaka": 1971, "lugha": "sw"},
    {"id": 3, "kichwa": "Things Fall Apart", "mwandishi": "Chinua Achebe", "mwaka": 1958, "lugha": "en"},
    {"id": 4, "kichwa": "Kiu", "mwandishi": "Mohammed Suleiman Mohammed", "mwaka": 1972, "lugha": "sw"},
    {"id": 5, "kichwa": "Weep Not, Child", "mwandishi": "Ngugi wa Thiong'o", "mwaka": 1964, "lugha": "en"},
    {"id": 6, "kichwa": "Utubora Mkulima", "mwandishi": "Shaaban Robert", "mwaka": 1968, "lugha": "sw"},
]


@app.get("/")
def mwanzo():
    return {"ujumbe": "Karibu Maktaba API"}


@app.get("/vitabu")
def orodha_vitabu(lugha: str | None = None, baada_ya: int | None = None, limit: int = 10):
    matokeo = [
        k for k in VITABU
        if (lugha is None or k["lugha"] == lugha)
        and (baada_ya is None or k["mwaka"] > baada_ya)
    ]
    return matokeo[:limit]


@app.get("/vitabu/{kitabu_id}")
def pata_kitabu(kitabu_id: int):
    for k in VITABU:
        if k["id"] == kitabu_id:
            return k
    return {"kosa": "Kitabu hakipo"}


@app.get("/waandishi")
def waandishi():
    return sorted({k["mwandishi"] for k in VITABU})

Kumbuka: /waandishi haigongani na /vitabu/{kitabu_id} kwa sababu path ni tofauti.

Kazi B — mteja.py

python
import requests

BASE = "http://127.0.0.1:8000"


def get(path: str, **params):
    r = requests.get(f"{BASE}{path}", params=params, timeout=5)
    r.raise_for_status()
    return r.json()


def main() -> None:
    try:
        vya_sw = get("/vitabu", lugha="sw")
        print("Vitabu vya Kiswahili:", len(vya_sw))
        print("Kitabu namba 2:", get("/vitabu/2")["kichwa"])
        print("Waandishi:", ", ".join(get("/waandishi")))
    except requests.ConnectionError:
        print("Server haiendeshi. Endesha: fastapi dev main.py")


if __name__ == "__main__":
    main()

Output:

text
Vitabu vya Kiswahili: 4
Kitabu namba 2: Rosa Mistika
Waandishi: Chinua Achebe, Euphrase Kezilahabi, Mohammed Suleiman Mohammed, Ngugi wa Thiong'o, Shaaban Robert

Kazi C

  1. Path param inatambulisha kitu kimoja hasa (/vitabu/2 = kitabu namba 2); query param inachuja/kurekebisha matokeo (/vitabu?lugha=sw = vitabu vya Kiswahili tu).
  2. 400 Bad Request (ombi baya), 401 Unauthorized (hujaingia), 404 Not Found (haipo), 422 (data si sahihi).
  3. Kwa sababu tunarudisha dict tu na FastAPI inaweka 200 kwa default. Inafaa kuwa 404 Not Found (tutatumia HTTPException Wiki 10).

Ukiulizwa swali usilolijua

Sema kwa uaminifu: "Swali zuri — sina uhakika, tutalitafuta pamoja" kisha tafuta mbele yake (ni somo pia: kujua kutafuta). Tafuta kwa Kiingereza mfano "fastapi query parameter list", "requests post json headers", "http status 409 meaning". Vyanzo rasmi: FastAPI Tutorial https://fastapi.tiangolo.com/tutorial/ · requests https://requests.readthedocs.io/ · MDN HTTP https://developer.mozilla.org/en-US/docs/Web/HTTP · JSONPlaceholder guide https://jsonplaceholder.typicode.com/guide/


Checklist ya mwisho wa wiki

  • Anaeleza client/server na request/response kwa analogy yake mwenyewe
  • Anavunja URL: scheme, host, port, path, query
  • Anajua kazi ya GET, POST, PUT, PATCH, DELETE
  • Anajua 200, 201, 204, 400, 401, 403, 404, 422, 500
  • Anatumia DevTools → Network kuona status na headers
  • Anatumia requests.get na params=, requests.post na json=
  • Daima anaweka timeout= na anatumia raise_for_status() ndani ya try/except
  • Anasakinisha "fastapi[standard]" ndani ya venv na kuendesha fastapi dev main.py
  • Anaandika path parameters na query parameters zenye type hints (pamoja na optional | None = None)
  • Anaelewa kwa nini 422 inatokea na anasoma detail yake
  • Anajua tatizo la route order
  • Anatumia /docs → "Try it out"
  • Kazi ya nyumbani iko GitHub na .venv haiko kwenye repo