Wiki 9: Jinsi Web Inavyofanya Kazi, requests, na Utangulizi wa FastAPI
Mwezi 3 | Lengo kuu: Mwanafunzi aelewe client/server na HTTP, atumie
requestskuongea na API ya umma, kisha ajenge API yake ya kwanza kwa FastAPI.
Maandalizi ya Mwalimu (soma kabla ya wiki kuanza)
- Soma:
- MDN — "An overview of HTTP": https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview
- MDN — HTTP status codes (pitia tu orodha): https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
requestsQuickstart: https://requests.readthedocs.io/en/latest/user/quickstart/- FastAPI Tutorial — "First Steps", "Path Parameters", "Query Parameters": https://fastapi.tiangolo.com/tutorial/first-steps/
- 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.
-
Andaa folda kwenye kompyuta ya kufundishia:
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 RemoteSignedkisha jibuY. -
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.
- VS Code extensions: Python (Microsoft). Hiari: "Thunder Client" au "REST Client" — lakini wiki hii tutatumia browser,
/docsya FastAPI, narequests, hivyo hazihitajiki. - 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...)
- Kueleza kwa maneno yake client na server ni nini, na request/response ni nini.
- Kuvunja URL katika sehemu zake: scheme, host, port, path, query string.
- Kutaja HTTP methods 5 kuu na kazi yake (GET, POST, PUT, PATCH, DELETE).
- Kutambua makundi ya status codes (2xx, 3xx, 4xx, 5xx) na codes muhimu: 200, 201, 204, 400, 401, 403, 404, 422, 500.
- Kutumia
requestskufanya GET na POST, kutuma query parameters, kusoma JSON, na kushughulikia errors (timeout, status mbaya). - Kusakinisha FastAPI na kuendesha server kwa
fastapi dev main.py. - Kuandika endpoints zenye path parameters na query parameters zenye type hints.
- Kutumia
/docs(Swagger UI) kujaribu API yake.
Kipindi 1 — Jinsi Web Inavyofanya Kazi: Client, Server, HTTP
Mtiririko wa kipindi
- Marudio ya kazi ya nyumbani ya Wiki 8 (Git/GitHub) — mwanafunzi aonyeshe repo yake
- Picha kubwa: client na server, request na response (analogy ya mgahawa)
- URL inavyoundwa: scheme, host, port, path, query
- HTTP methods na status codes
- JSON ni nini na kwa nini API zinaitumia; kufungua API kwenye browser
- DevTools ya browser: kuona requests halisi (Network tab)
- Zoezi darasani
- 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 zakey=valuezilizotenganishwa 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 Content3xx— redirect (nenda mahali pengine):301,302,3044xx— 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:
httpsni 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:
https://jsonplaceholder.typicode.com/todos/1
Output inayotarajiwa (browser inaonyesha 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 mmojahttps://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:
Invoke-RestMethod https://jsonplaceholder.typicode.com/todos/1
Output:
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):
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:
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:
<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):
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:
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
- Browser yako ni client au server? — Client.
- Ukifungua YouTube kwenye simu, nani ni client na nani ni server? — App ya YouTube kwenye simu ni client; kompyuta za Google ni server.
GET /postsnaPOST /postsni endpoint moja? — Hapana, ni mbili tofauti; method ni sehemu ya endpoint.- Status 404 maana yake nini, na ni kosa la nani? — Haipatikani; kundi la 4xx ni kosa la client (umeomba kitu kisichokuwepo).
- Tofauti ya 401 na 403? — 401: server haikujui (hujaingia/login). 403: inakujua lakini huna ruhusa.
- 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. - 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.
- Ukitaka kubadilisha namba ya simu tu ya mteja, utatumia method gani? — PATCH (au PUT kama unatuma mteja mzima).
- 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, host127.0.0.1(port 8000), path/items/5, queryq=simu - b) scheme
https, hostapi.github.com, path/users/octocat/repos, queryper_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(au400 Bad Request)
1.3 Status 200, content-type: application/json; charset=utf-8, comments 5.
1.4
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:
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
- Marudio ya kazi ya nyumbani (maswali ya HTTP / script ya URL)
- Kusakinisha
requestsndani ya venv; kwa nini siurllib requests.get: status_code, headers,.json(),params=requests.postkwajson=; kusoma 201- Errors:
timeout,raise_for_status(),ConnectionError - Mini-project: pakua todos, chuja, hifadhi kwenye faili JSON
- Zoezi darasani
- 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 yaResponse.response.status_code→ namba (mfano200).response.ok→Truekama 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 (inafanyajson.loadskwa 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 headerContent-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, inarusharequests.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.
requestsni 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.""
timeoutni 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):
pip install requests pip show requests
Hatua 2 — GET ya kwanza. Unda api_1.py:
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:
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:
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:
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:
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:
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:
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:
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:
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:
Nimehifadhi todos 12 kwenye todos_user2.json
Fungua todos_user2.json ndani ya VS Code umwonyeshe.
Maswali ya kumuuliza mwanafunzi
response.json()inarudisha nini kwa/todos/1na kwa/todos? — Ya kwanza dict, ya pili list (ya dicts).- Kwa nini tunatumia
params={...}badala ya kuandika?userId=1kwenye string? — Requests inajenga na ku-encode query vizuri (nafasi, alama maalum), na code inasomeka zaidi. - Tofauti ya
json=naparams=? —paramsinaenda kwenye URL (query string);jsoninaenda kwenye body. - Usipoweka
timeoutkuna hatari gani? — Script inaweza kusubiri milele server isipojibu. raise_for_status()inafanya nini kwenye status 200? — Hakuna kitu; inarusha error kwa 4xx/5xx tu.- Kwa nini GET
/posts/101ni 404 baada ya POST kufanikiwa? — JSONPlaceholder ni API bandia; haihifadhi data. requests.get(...)ikifanikiwa lakini status ni 404, je exception inarushwa? — Hapana! Isipokuwa ukiitaraise_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
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):
Leanne Graham Gwenborough Ervin Howell Wisokyburgh Clementine Bauch McKenziehaven ...
2.2
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
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
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
- Marudio ya kazi ya nyumbani (scripts za requests)
- FastAPI ni nini; sasa SISI ndio server
- Kusakinisha,
main.pyya kwanza,fastapi dev main.py /docsna/redoc— documentation ya bure- Path parameters zenye types; 422 ikiwa type si sahihi
- Query parameters: default, optional (
None), bool - Kuita API yetu wenyewe kwa
requests - Zoezi darasani
- 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:
- Kugeuza data (conversion) —
"5"kutoka URL inakuwa5(int). - Kuthibitisha data (validation) —
"abc"kwaintinarudisha 422 na maelezo. - Documentation —
/docsinajengwa 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.""
/docsni 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.
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:
from fastapi import FastAPI app = FastAPI(title="API ya Kwanza") @app.get("/") def mwanzo(): return {"ujumbe": "Karibu kwenye API yangu!"}
Endesha:
fastapi dev main.py
Output (sehemu muhimu):
⚡️ 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:
{"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):
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:
{"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 tutajifunzaHTTPExceptionkurekebisha hili." (Hii ni ndoano nzuri ya Wiki 10.)
Hatua 5 — Query parameters. Ongeza:
@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}:
@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:
[{"jina":"Daftari","bei":1000,"aina":"shule"},{"jina":"Kalamu","bei":500,"aina":"shule"}]
Hatua 7 — Required query na bool:
@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:
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:
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
- Kwa nini tunaandika
"fastapi[standard]"kwa nukuu? — PowerShell inaweza kutafsiri mabano[ ]; nukuu zinahakikisha pip inapokea jina lote.[standard]inaleta uvicorn na zana nyingine. fastapi devinafanya nini ukihifadhi faili? — Inajiwasha upya (reload) yenyewe.- Ukiandika
def pata(bidhaa_id: int)na path ni/bidhaa/{id}, nini kitatokea? — Majina hayalingani; FastAPI itachukuliabidhaa_idkama query parameter ya lazima, naidya path haitumiki → 422 ukikosa?bidhaa_id=. Majina lazima yafanane. - Ni lini query parameter ni ya lazima? — Ikiwa haina default.
- Kwa nini
/bidhaa/nafuuilitoa 422 mwanzoni? — Route order:{bidhaa_id}ilikamata "nafuu" kwanza. - Function inarudisha dict; client anapokea nini? — JSON (FastAPI inageuza).
/bidhaa/99ilirudisha status gani na ni sahihi? — 200; si sahihi, inapaswa kuwa 404 (tutarekebisha Wiki 10).127.0.0.1ni 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
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:
GET /→ ujumbe wa kukaribisha.GET /vitabu→ query params:lugha: str | None = None,baada_ya: int | None = None(vitabu vya mwaka mkubwa kuliko huu),limit: int = 10.GET /vitabu/{kitabu_id}→ kitabu kimoja; kama hakipo rudisha{"kosa": "Kitabu hakipo"}.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):
- Eleza kwa maneno yako tofauti ya path parameter na query parameter, kwa mfano wako mwenyewe.
- Taja status codes 3 za kundi la 4xx na maana yake.
- Kwa nini
GET /vitabu/99yako inarudisha 200 ingawa kitabu hakipo, na ni status gani ingefaa?
Jibu
Kazi A — main.py
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
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:
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
- Path param inatambulisha kitu kimoja hasa (
/vitabu/2= kitabu namba 2); query param inachuja/kurekebisha matokeo (/vitabu?lugha=sw= vitabu vya Kiswahili tu). - 400 Bad Request (ombi baya), 401 Unauthorized (hujaingia), 404 Not Found (haipo), 422 (data si sahihi).
- Kwa sababu tunarudisha dict tu na FastAPI inaweka 200 kwa default. Inafaa kuwa 404 Not Found (tutatumia
HTTPExceptionWiki 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.getnaparams=,requests.postnajson= - Daima anaweka
timeout=na anatumiaraise_for_status()ndani yatry/except - Anasakinisha
"fastapi[standard]"ndani ya venv na kuendeshafastapi dev main.py - Anaandika path parameters na query parameters zenye type hints (pamoja na optional
| None = None) - Anaelewa kwa nini 422 inatokea na anasoma
detailyake - Anajua tatizo la route order
- Anatumia
/docs→ "Try it out" - Kazi ya nyumbani iko GitHub na
.venvhaiko kwenye repo