IlmHamroh
Python kursi/Web backend FastAPI4/16-dars16 daqiqa
Mundarija (22)

20.4-dars: Route va parametrlar

20-QISM — WEB-BACKEND (FastAPI) · 4-dars


1. Kirish va motivatsiya

Birinchi FastAPI ilovani yaratdik 20.3-bob. Endi endpointlar ma'lumot qabul qilishni — parametrlarni o'rganamiz. Real API'da so'rovlar ma'lumot tashiydi: /kurslar/5 — qaysi kurs (yo'l parametri); /kurslar?til=uz&sahifa=2 — filtr va sahifalash (so'rov parametrlari). FastAPI bu parametrlarni tip belgilari bilan qabul qiladi, tekshiradi va aylantiradi — avtomatik.

Parametrlar API'ni moslashuvchan qiladi: bir endpoint turli kirish bilan turli natija beradi. Ularni to'g'ri loyihalash — REST API dizaynining muhim qismi.

Real vaziyat. Bir jamoa qidiruv endpointi yozdi, lekin parametrlarni tekshirmasdi: sahifa manfiy bo'lsa baza xatosi, hajm 10000 bo'lsa server osilib qolardi, qidiruv so'zi bo'sh bo'lsa barcha ma'lumot qaytardi. Ular FastAPI validatsiyasini qo'shdi: sahifa >= 1, hajm <= 100, qidiruv min_length=2. Endi noto'g'ri so'rov 422 aniq xato beradi (server osilmaydi), va cheklovlar hujjatda avtomatik ko'rinadi. Parametr validatsiyasi API'ni mustahkam qildi.

Bu darsda route parametrlarini — yo'l va so'rov parametrlarini o'rganamiz.

Bu darsda:

  • Yo'l parametrlari ({kurs_id})
  • So'rov parametrlari (?til=uz)
  • Ixtiyoriy va majburiy parametrlar
  • Standart qiymatlar
  • Parametr validatsiyasi (Query, Path)
  • Tur aylantirish
  • Parametr tartibi
  • Amaliy: filtrlash va sahifalash

ℹ Misollarda FastAPI TestClient bilan sinaladi.


2. Nazariya — chuqur tushuntirish

2.1. Yo'l parametrlari

Yo'l parametri — URL yo'lidagi o'zgaruvchi qism ({...}):

python
@app.get("/kurslar/{kurs_id}")
def kurs(kurs_id: int):        # {kurs_id} → funksiya parametri
    return {"id": kurs_id}
Element Ma'nosi
{kurs_id} Yo'ldagi o'zgaruvchi
kurs_id: int Tur (validatsiya + aylantirish)
/kurslar/5 kurs_id = 5

Yo'l parametrlari — resursni aniqlash uchun (/kurslar/5 — 5-kurs). Ular majburiy (yo'lning bir qismi).

2.2. So'rov parametrlari

So'rov parametri — URL'ning ? dan keyingi qismi 20.1-bob:

python
@app.get("/kurslar")
def kurslar(til: str = "uz", sahifa: int = 1):   # ?til=uz&sahifa=2
    return {"til": til, "sahifa": sahifa}
Element Ma'nosi
Funksiya parametri (yo'lda yo'q) So'rov parametri
til: str = "uz" Ixtiyoriy, standart "uz"
?til=en&sahifa=2 til="en", sahifa=2

So'rov parametrlari — to'plamni sozlash (filtr, saralash, sahifalash). Ular ko'pincha ixtiyoriy (standart qiymatli).

2.3. Ixtiyoriy va majburiy

Parametr Majburiy?
Standart qiymatsiz Majburiy
Standart qiymatli Ixtiyoriy
str | None = None Ixtiyoriy (None bo'lishi mumkin)
python
def qidir(q: str):                 # majburiy (standartsiz)
def sahifala(sahifa: int = 1):     # ixtiyoriy (standart 1)
def filtr(til: str | None = None): # ixtiyoriy (None bo'lishi mumkin)

Majburiy so'rov parametri berilmasa — 422 xato. Ixtiyoriy — standart yoki None.

2.4. Tur aylantirish

FastAPI parametrlarni tip belgisiga qarab aylantiradi:

Tip belgisi Kirish Natija
int "5" 5 (int)
float "2.5" 2.5
bool "true", "1" True
str "uz" "uz"

URL parametrlari matn bo'lsa ham, FastAPI ularni tipga aylantiradi; aylantirib bo'lmasa 422.

2.5. Parametr validatsiyasi

Query va Path bilan qo'shimcha tekshiruvlar:

python
from fastapi import Query, Path
from typing import Annotated

@app.get("/kurslar/{kurs_id}")
def kurs(
    kurs_id: Annotated[int, Path(ge=1)],                    # >= 1
    sahifa: Annotated[int, Query(ge=1, le=100)] = 1,        # 1-100
    q: Annotated[str, Query(min_length=2, max_length=50)] = "",
):
    ...
Cheklov Ma'nosi
ge, gt >= / > (son)
le, lt <= / < (son)
min_length, max_length Satr uzunligi
pattern Regex (4-qism)

Validatsiya cheklovlari hujjatda (/docs) avtomatik ko'rinadi va buzilsa 422 beradi.

2.6. Annotated sintaksisi

Zamonaviy FastAPI Annotated (13-qism) ishlatadi:

python
# eski:
sahifa: int = Query(default=1, ge=1)
# zamonaviy (tavsiya):
sahifa: Annotated[int, Query(ge=1)] = 1

Annotated[tip, Query(...)] — tur va validatsiyani ajratadi; standart qiymat = bilan. Bu aniqroq va tavsiya etiladi.

2.7. Parametr tartibi va aralashtirish

Bir endpoint yo'l va so'rov parametrlarini birga qabul qiladi:

python
@app.get("/kurslar/{kurs_id}/darslar")
def darslar(kurs_id: int, sahifa: int = 1, til: str = "uz"):
    # kurs_id — yo'l; sahifa, til — so'rov
    ...

FastAPI qaysi parametr yo'lda ({...} bor) va qaysi so'rovda ekanini avtomatik aniqlaydi. Yo'ldagi nom — yo'l parametri, qolgani so'rov.

2.8. Javob va status kod

python
from fastapi import HTTPException

@app.get("/kurslar/{kurs_id}")
def kurs(kurs_id: int):
    if kurs_id not in KURSLAR:
        raise HTTPException(status_code=404, detail="topilmadi")
    return KURSLAR[kurs_id]

Parametr topilsa — natija (200); topilmasa — HTTPException(404). To'g'ri status kod 20.1-bob muhim.


3. Tez ma'lumotnoma

python
from fastapi import FastAPI, Query, Path
from typing import Annotated

@app.get("/kurslar/{kurs_id}")
def kurs(
    kurs_id: Annotated[int, Path(ge=1)],           # yo'l parametri
    til: str = "uz",                               # so'rov (ixtiyoriy)
    sahifa: Annotated[int, Query(ge=1, le=100)] = 1,
    q: str | None = None,                          # ixtiyoriy (None)
):
    ...

Qoidalar

yo'l parametri ({kurs_id}) — resursni aniqlash (majburiy)
so'rov parametri (?til=uz) — sozlash (ko'pincha ixtiyoriy)
standartsiz — majburiy; standartli — ixtiyoriy
tip belgisi → aylantirish + validatsiya
Query/Path — qo'shimcha tekshiruv (ge, le, min_length)
Annotated[tip, Query(...)] — zamonaviy sintaksis

4. Batafsil misollar

Misollarda FastAPI TestClient bilan sinaladi.

Misol 1 — Yo'l va so'rov parametrlari

python
"""yo'l parametri ({kurs_id}); so'rov parametrlari (til, sahifa); ixtiyoriy vs majburiy; standart qiymatlar; tur aylantirish."""

import warnings
warnings.filterwarnings("ignore")

from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()


@app.get("/kurslar/{kurs_id}")
def kurs(kurs_id: int, til: str = "uz", batafsil: bool = False):
    return {"id": kurs_id, "til": til, "batafsil": batafsil}


def main() -> None:
    client = TestClient(app)

    print("=== 1. Yo'l parametri ===")
    print(f"  /kurslar/5 → {client.get('/kurslar/5').json()}")

    print("\n=== 2. So'rov parametrlari ===")
    print(f"  /kurslar/5?til=en → {client.get('/kurslar/5?til=en').json()}")
    print(f"  /kurslar/5?til=en&batafsil=true → {client.get('/kurslar/5?til=en&batafsil=true').json()}")

    print("\n=== 3. Standart qiymatlar ===")
    print(f"  /kurslar/5 (til va batafsil sukut): {client.get('/kurslar/5').json()}")

    print("\n=== 4. Tur aylantirish ===")
    javob = client.get("/kurslar/5?batafsil=1").json()
    print(f"  batafsil=1 → {javob['batafsil']} (bool: {type(javob['batafsil']).__name__})")
    javob = client.get("/kurslar/42").json()
    print(f"  kurs_id '42' → {javob['id']} (int: {type(javob['id']).__name__})")
    print("  ⭐ yo'l parametri — resurs; so'rov parametri — sozlash")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Yo'l parametri ===
  /kurslar/5 → {'id': 5, 'til': 'uz', 'batafsil': False}

=== 2. So'rov parametrlari ===
  /kurslar/5?til=en → {'id': 5, 'til': 'en', 'batafsil': False}
  /kurslar/5?til=en&batafsil=true → {'id': 5, 'til': 'en', 'batafsil': True}

=== 3. Standart qiymatlar ===
  /kurslar/5 (til va batafsil sukut): {'id': 5, 'til': 'uz', 'batafsil': False}

=== 4. Tur aylantirish ===
  batafsil=1 → True (bool: bool)
  kurs_id '42' → 42 (int: int)
  ⭐ yo'l parametri — resurs; so'rov parametri — sozlash

Nima ko'rsatdi: 2.1, 2.2, 2.3, 2.4-bo'limlar.

Misol 2 — Parametr validatsiyasi (Query, Path)

python
"""Query va Path bilan validatsiya: ge/le (son oralig'i), min_length/max_length (satr); buzilsa 422; cheklovlar hujjatda."""

import warnings
warnings.filterwarnings("ignore")

from typing import Annotated

from fastapi import FastAPI, Path, Query
from fastapi.testclient import TestClient

app = FastAPI()


@app.get("/kurslar/{kurs_id}")
def kurs(
    kurs_id: Annotated[int, Path(ge=1)],
    sahifa: Annotated[int, Query(ge=1, le=100)] = 1,
):
    return {"id": kurs_id, "sahifa": sahifa}


@app.get("/qidir")
def qidir(q: Annotated[str, Query(min_length=2, max_length=20)]):
    return {"q": q, "natija": []}


def main() -> None:
    client = TestClient(app)

    print("=== 1. To'g'ri parametrlar ===")
    print(f"  /kurslar/5?sahifa=3 → {client.get('/kurslar/5?sahifa=3').json()}")

    print("\n=== 2. ⚠️ Path ge=1 buzilishi ===")
    javob = client.get("/kurslar/0")
    print(f"  /kurslar/0 → status {javob.status_code} (kurs_id >= 1 kerak)")

    print("\n=== 3. ⚠️ Query le=100 buzilishi ===")
    javob = client.get("/kurslar/5?sahifa=200")
    print(f"  /kurslar/5?sahifa=200 → status {javob.status_code} (sahifa <= 100)")

    print("\n=== 4. ⚠️ Satr uzunligi ===")
    print(f"  /qidir (q majburiy) → status {client.get('/qidir').status_code}")
    print(f"  /qidir?q=a (juda qisqa) → status {client.get('/qidir?q=a').status_code}")
    print(f"  /qidir?q=python (to'g'ri) → {client.get('/qidir?q=python').json()}")
    print("  ⭐ Query/Path validatsiyasi — noto'g'ri kirish 422 (server osilmaydi)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. To'g'ri parametrlar ===
  /kurslar/5?sahifa=3 → {'id': 5, 'sahifa': 3}

=== 2. ⚠️ Path ge=1 buzilishi ===
  /kurslar/0 → status 422 (kurs_id >= 1 kerak)

=== 3. ⚠️ Query le=100 buzilishi ===
  /kurslar/5?sahifa=200 → status 422 (sahifa <= 100)

=== 4. ⚠️ Satr uzunligi ===
  /qidir (q majburiy) → status 422
  /qidir?q=a (juda qisqa) → status 422
  /qidir?q=python (to'g'ri) → {'q': 'python', 'natija': []}
  ⭐ Query/Path validatsiyasi — noto'g'ri kirish 422 (server osilmaydi)

Nima ko'rsatdi: 2.5, 2.6-bo'limlar.

Misol 3 — Ixtiyoriy parametrlar va filtr

python
"""ixtiyoriy parametrlar (None); bir necha filtr; standart qiymatlar; None tekshiruvi; kombinatsiyalangan filtr."""

import warnings
warnings.filterwarnings("ignore")

from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()

KURSLAR = [
    {"id": 1, "nom": "Python", "til": "uz", "daraja": "boshlangich"},
    {"id": 2, "nom": "JavaScript", "til": "uz", "daraja": "orta"},
    {"id": 3, "nom": "Go", "til": "en", "daraja": "orta"},
    {"id": 4, "nom": "Rust", "til": "en", "daraja": "yuqori"},
]


@app.get("/kurslar")
def kurslar(til: str | None = None, daraja: str | None = None):
    natija = KURSLAR
    if til:
        natija = [k for k in natija if k["til"] == til]
    if daraja:
        natija = [k for k in natija if k["daraja"] == daraja]
    return natija


def main() -> None:
    client = TestClient(app)

    print("=== 1. Filtrsiz (barchasi) ===")
    print(f"  /kurslar → {len(client.get('/kurslar').json())} kurs")

    print("\n=== 2. Bitta filtr ===")
    print(f"  ?til=uz → {[k['nom'] for k in client.get('/kurslar?til=uz').json()]}")
    print(f"  ?daraja=orta → {[k['nom'] for k in client.get('/kurslar?daraja=orta').json()]}")

    print("\n=== 3. Kombinatsiyalangan filtr ===")
    javob = client.get("/kurslar?til=en&daraja=orta")
    print(f"  ?til=en&daraja=orta → {[k['nom'] for k in javob.json()]}")

    print("\n=== 4. Ixtiyoriy (None) mantig'i ===")
    print("  til=None → filtr qo'llanmaydi (barcha til)")
    print("  til='uz' → faqat o'zbek tilidagi")
    print("  ⭐ ixtiyoriy parametr (None) — filtrni yoqish/o'chirish")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Filtrsiz (barchasi) ===
  /kurslar → 4 kurs

=== 2. Bitta filtr ===
  ?til=uz → ['Python', 'JavaScript']
  ?daraja=orta → ['JavaScript', 'Go']

=== 3. Kombinatsiyalangan filtr ===
  ?til=en&daraja=orta → ['Go']

=== 4. Ixtiyoriy (None) mantig'i ===
  til=None → filtr qo'llanmaydi (barcha til)
  til='uz' → faqat o'zbek tilidagi
  ⭐ ixtiyoriy parametr (None) — filtrni yoqish/o'chirish

Nima ko'rsatdi: 2.3, 2.7-bo'limlar.

Misol 4 — Amaliy: filtrlash, saralash, sahifalash

To'liq kurslar API sini barcha parametr turlari bilan yaratamiz: yo'l parametri (bitta kurs), so'rov parametrlari (filtr, saralash, sahifalash) va validatsiya. Bu — real API'ning to'plam endpointi: filtrlanadigan, saralanadigan, sahifalanadigan.

python
"""to'liq to'plam endpointi: filtr (til), saralash (sort, order), sahifalash (sahifa, hajm) validatsiya bilan; yo'l parametri (bitta kurs); 404."""

import warnings
warnings.filterwarnings("ignore")

from typing import Annotated

from fastapi import FastAPI, HTTPException, Path, Query
from fastapi.testclient import TestClient

app = FastAPI(title="Wisar Kurslar API")

KURSLAR = [
    {"id": 1, "nom": "Python", "til": "uz", "narx": 100},
    {"id": 2, "nom": "JavaScript", "til": "uz", "narx": 80},
    {"id": 3, "nom": "Go", "til": "en", "narx": 120},
    {"id": 4, "nom": "Rust", "til": "en", "narx": 150},
    {"id": 5, "nom": "Java", "til": "uz", "narx": 90},
]


@app.get("/kurslar")
def kurslar(
    til: str | None = None,
    sort: Annotated[str, Query(pattern="^(id|nom|narx)$")] = "id",
    order: Annotated[str, Query(pattern="^(asc|desc)$")] = "asc",
    sahifa: Annotated[int, Query(ge=1)] = 1,
    hajm: Annotated[int, Query(ge=1, le=100)] = 10,
):
    natija = [k for k in KURSLAR if not til or k["til"] == til]
    natija = sorted(natija, key=lambda k: k[sort] if sort in ("nom", "narx") else k["id"], reverse=(order == "desc"))
    boshi = (sahifa - 1) * hajm
    return {"jami": len(natija), "sahifa": sahifa, "kurslar": natija[boshi:boshi + hajm]}


@app.get("/kurslar/{kurs_id}")
def bitta_kurs(kurs_id: Annotated[int, Path(ge=1)]):
    for k in KURSLAR:
        if k["id"] == kurs_id:
            return k
    raise HTTPException(status_code=404, detail="kurs topilmadi")


def main() -> None:
    client = TestClient(app)

    print("=== 1. Filtr + sahifalash ===")
    javob = client.get("/kurslar?til=uz&hajm=2").json()
    print(f"  ?til=uz&hajm=2 → jami {javob['jami']}, sahifada {[k['nom'] for k in javob['kurslar']]}")

    print("\n=== 2. Saralash ===")
    javob = client.get("/kurslar?sort=narx&order=desc").json()
    print(f"  ?sort=narx&order=desc → {[(k['nom'], k['narx']) for k in javob['kurslar']]}")

    print("\n=== 3. Sahifalash ===")
    javob = client.get("/kurslar?sahifa=2&hajm=2").json()
    print(f"  ?sahifa=2&hajm=2 → {[k['nom'] for k in javob['kurslar']]}")

    print("\n=== 4. Validatsiya ===")
    print(f"  ?sort=xato → status {client.get('/kurslar?sort=xato').status_code} (pattern)")
    print(f"  ?hajm=200 → status {client.get('/kurslar?hajm=200').status_code} (le=100)")

    print("\n=== 5. Bitta kurs va 404 ===")
    print(f"  /kurslar/1 → {client.get('/kurslar/1').json()['nom']}")
    print(f"  /kurslar/999 → status {client.get('/kurslar/999').status_code}")
    print("  ⭐ filtr + saralash + sahifalash + validatsiya = to'liq API")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Filtr + sahifalash ===
  ?til=uz&hajm=2 → jami 3, sahifada ['Python', 'JavaScript']

=== 2. Saralash ===
  ?sort=narx&order=desc → [('Rust', 150), ('Go', 120), ('Python', 100), ('Java', 90), ('JavaScript', 80)]

=== 3. Sahifalash ===
  ?sahifa=2&hajm=2 → ['Go', 'Rust']

=== 4. Validatsiya ===
  ?sort=xato → status 422 (pattern)
  ?hajm=200 → status 422 (le=100)

=== 5. Bitta kurs va 404 ===
  /kurslar/1 → Python
  /kurslar/999 → status 404
  ⭐ filtr + saralash + sahifalash + validatsiya = to'liq API

Nima ko'rsatdi: 2.1–2.8-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"Barcha parametr yo'lda" Yo'l — resurs; so'rov — sozlash
"Parametrni qo'lda aylantirish" Tip belgisi avtomatik
"Validatsiyani qo'lda" Query/Path beradi
"Standartsiz — ixtiyoriy" Standartsiz — majburiy
"Filtr yo'lda" Filtr — so'rov parametri
"Noto'g'ri kirish server osadi" Validatsiya → 422
"Parametr tartibini belgilash kerak" FastAPI avtomatik aniqlaydi
"Annotated keraksiz" Zamonaviy, tavsiya etiladi

6. Keng tarqalgan xatolar va yechimlari

1. Validatsiyasiz parametr

python
def sahifala(sahifa: int = 1):              # ⚠️ manfiy bo'lishi mumkin
def sahifala(sahifa: Annotated[int, Query(ge=1)] = 1):   # ✅

2. Filtrni yo'lda

python
@app.get("/kurslar/til/{til}")              # ❌ filtr — parametr
@app.get("/kurslar")  # ?til=uz             # ✅

3. Majburiy filtr

python
def kurslar(til: str):                      # ❌ filtr majburiy bo'ldi
def kurslar(til: str | None = None):        # ✅ ixtiyoriy

4. Turni qo'lda aylantirish

python
def kurs(kurs_id: str):
    kurs_id = int(kurs_id)                   # ❌ qo'lda
def kurs(kurs_id: int):                     # ✅ avtomatik

5. Cheklovsiz hajm

python
def kurslar(hajm: int = 10):                # ⚠️ 10000 bo'lishi mumkin
def kurslar(hajm: Annotated[int, Query(le=100)] = 10):   # ✅

6. HTTPException o'rniga oddiy javob

python
return {"xato": "topilmadi"}                # ⚠️ status 200
raise HTTPException(404, "topilmadi")       # ✅

7. Eski Query sintaksisi

python
sahifa: int = Query(default=1, ge=1)        # eski
sahifa: Annotated[int, Query(ge=1)] = 1     # ✅ zamonaviy

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 20.2-dars (o'tilgan): REST — parametrlar (filtr, sahifalash)
  • 20.3-dars (o'tilgan): FastAPI — endpoint asoslari
  • 13-qism (o'tilgan): Annotated, tip belgilari
  • 20.5-dars: Pydantic — tana (body) validatsiyasi
  • 20.6-dars: so'rov va javob — chuqurroq

8. Eng yaxshi amaliyotlar

  1. Yo'l parametrlari — resursni aniqlash; so'rov — sozlash.

  2. Filtr/saralash/sahifalash — so'rov parametrlari (ixtiyoriy).

  3. Query/Path bilan validatsiya (ge, le, min_length).

  4. Annotated[tip, Query(...)] — zamonaviy sintaksis.

  5. Ixtiyoriy parametrlar — str | None = None yoki standart.

  6. hajm kabi parametrlarni cheklang (le) — server himoyasi.

  7. Topilmaganda HTTPException(404).

  8. Tip belgilariga tayaning — aylantirish avtomatik.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # {kurs_id} nima?
2.  # ?til=uz nima?
3.  # def f(sahifa: int = 1) — majburiymi?
4.  # def f(q: str) — majburiymi?
5.  # Query(ge=1) nima tekshiradi?
6.  # kurs_id: int, '5' → ?
7.  # sahifa manfiy bo'lsa (ge=1)?
8.  # str | None = None nima?
9.  # yo'l va so'rov parametrini kim aniqlaydi?
10. # min_length nima tekshiradi?
11. # Annotated nima uchun?
12. # noto'g'ri parametr status kodi?
Javoblar
  1. Yo'l parametri
  2. So'rov parametri
  3. Yo'q (ixtiyoriy, standart 1)
  4. Ha (standartsiz)
  5. Son >= 1
  6. 5 (int, avtomatik)
  7. 422
  8. Ixtiyoriy parametr (None bo'lishi mumkin)
  9. FastAPI (yo'lda {...} bor-yo'qligiga qarab)
  10. Satr minimal uzunligi
  11. Tur + validatsiyani ajratish (zamonaviy)
  12. 422

Vazifa 2: Xatolarni tuzating

python
1.  @app.get("/kurslar/til/{til}")
    def kurslar(til: str): ...     # filtr yo'lda

2.  def kurslar(til: str):          # filtr majburiy
        ...

3.  def sahifala(sahifa: int = 1):  # cheklovsiz
        ...

4.  def kurs(kurs_id: str):
        kurs_id = int(kurs_id)      # qo'lda aylantirish

5.  def kurs(kurs_id: int):
        if kurs_id not in KURSLAR:
            return {"xato": "yo'q"}  # status 200
Javoblar
python
1.  @app.get("/kurslar")
    def kurslar(til: str | None = None): ...   # filtr — parametr

2.  def kurslar(til: str | None = None):       # ixtiyoriy

3.  def sahifala(sahifa: Annotated[int, Query(ge=1, le=100)] = 1):

4.  def kurs(kurs_id: int):                    # avtomatik

5.  def kurs(kurs_id: int):
        if kurs_id not in KURSLAR:
            raise HTTPException(404, "yo'q")

Vazifa 3: Filtrlanadigan API

"Mahsulotlar" API:

  1. Filtrlar: kategoriya, narx oralig'i (narx_min, narx_max)
  2. Saralash (sort, order)
  3. Sahifalash validatsiya bilan
  4. TestClient bilan test

Vazifa 4: Validatsiya to'plami

Turli validatsiyali endpointlar:

  1. ge/le (son oralig'i)
  2. min_length/max_length (satr)
  3. pattern (regex — email, telefon)
  4. Har biri uchun 422 test

Vazifa 5: Yo'l vs so'rov

  1. Bir endpointda yo'l va so'rov parametrlari
  2. Ichma-ich yo'l (/kurslar/{id}/darslar/{dars_id})
  3. Aralash validatsiya
  4. FastAPI qanday aniqlashini hujjatlang

Vazifa 6: Sahifalash mantig'i

To'liq sahifalash:

  1. sahifa, hajm validatsiya bilan
  2. Jami soni, sahifalar soni
  3. keyingi/oldingi sahifa havolalari (HATEOAS)
  4. Chegara holatlari (bo'sh, oxirgi sahifa)

Vazifa 7: O'ylash

FastAPI parametr validatsiyasini deklarativ qiladi: Query(ge=1, le=100) — "nima" ni aytasiz, "qanday tekshirish" ni FastAPI qiladi. Bu imperativ (if sahifa < 1: raise ...) validatsiyadan farq qiladi. Nima uchun deklarativ validatsiya afzal, va bu "nima vs qanday" farqi dasturlashda qayerda uchraydi?

Javob

Qisqa javob: Deklarativ validatsiya afzal, chunki u niyatni (nima kerak) ifodalaydi, mexanizmni (qanday tekshirish) emas — FastAPI qanday tekshirishni biladi. Bu qisqaroq, o'qiladigan, xatosiz va — muhimi — hujjatga avtomatik aylanadi (cheklov /docsda ko'rinadi). Imperativ kod (if/raise) har tekshiruvni qo'lda yozadi, takrorlanadi, hujjatga aylanmaydi. "Nima vs qanday" farqi dasturlashda keng: SQL (deklarativ) vs sikl, regex vs tahlil kodi, konfiguratsiya vs kod.

1. Deklarativ vs imperativ

Imperativ (qanday) Deklarativ (nima)
if sahifa < 1: raise ... Query(ge=1)
Har tekshiruv qo'lda Cheklov e'lon qilinadi
Takror Qisqa
Hujjatga aylanmaydi Hujjat avtomatik

2. Nega deklarativ afzal

Foyda Tafsilot
Qisqa Kam kod
O'qiladigan Niyat aniq
Hujjat Cheklov ko'rinadi
Xatosiz Framework tekshiradi
Izchil Bir xil format

3. "Nima vs qanday" boshqa joyda

Deklarativ (nima) Imperativ (qanday)
SQL (SELECT ... WHERE) Sikl bilan filtr
Regex (naqsh) Tahlil kodi
Query(ge=1) if/raise
Konfiguratsiya Kod
HTML/CSS Chizish kodi

4. Deklarativ kuchi

Deklarativ kod nima kerakligini aytadi, tizim qanday qilishni hal qiladi. Bu:

  • Optimizatsiya tizimga qoladi
  • Kod niyatga yaqin
  • Ko'p natija (validatsiya + hujjat)

5. Muhandislik saboqlari

  1. Niyatni ifodala (nima), mexanizmni yashir (qanday)
  2. Deklarativ — qisqa, o'qiladigan, hujjatga aylanadi
  3. Framework mexanizmni biladi
  4. "Nima vs qanday" — dasturlashning asosiy farqi

6. Xulosa

  1. Deklarativ validatsiya niyatni ifodalaydi
  2. FastAPI cheklovni tekshiradi va hujjatlaydi
  3. Imperativ (if/raise) — takror, hujjatsiz
  4. "Nima vs qanday" tamoyili keng qo'llaniladi

Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.


Xulosa

Bu darsda route parametrlarini — yo'l va so'rov parametrlarini o'rgandik.

Eng muhim uch fikr:

  1. Yo'l va so'rov parametrlari — turli maqsad. Yo'l parametrlari ({kurs_id}) resursni aniqlaydi (/kurslar/5 — 5-kurs), majburiy (yo'lning bir qismi). So'rov parametrlari (?til=uz&sahifa=2) to'plamni sozlaydi (filtr, saralash, sahifalash), ko'pincha ixtiyoriy (standart qiymatli). FastAPI qaysi parametr yo'lda, qaysi so'rovda ekanini avtomatik aniqlaydi va tip belgisiga qarab aylantiradi.

  2. Ixtiyoriy/majburiy va validatsiya. Standart qiymatsiz parametr — majburiy (berilmasa 422); standart qiymatli yoki str | None = None — ixtiyoriy. Query va Path qo'shimcha validatsiya beradi: ge/le (son oralig'i), min_length/max_length (satr), pattern (regex). Zamonaviy sintaksis — Annotated[tip, Query(...)] = standart. Validatsiya buzilsa 422 (server osilmaydi) va cheklovlar hujjatda avtomatik ko'rinadi.

  3. To'liq to'plam endpointi. Real API to'plam endpointi filtr (so'rov parametri), saralash (sort, order — pattern bilan cheklangan), sahifalash (sahifa, hajm — ge/le bilan) ni birlashtiradi. hajm kabi parametrlarni cheklash (le=100) — server himoyasi. FastAPI validatsiyasi deklarativ — "nima kerak" ni aytasiz (Query(ge=1)), "qanday tekshirish" ni FastAPI qiladi, va cheklov avtomatik hujjatga aylanadi.

Keyingi darsda Pydantic modellari ni o'rganamiz: so'rov tanasini (body) — murakkab JSON ma'lumotni — model bilan qabul qilish, validatsiya va seriyalizatsiya.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
20.4-dars: Route va parametrlar — IlmHamroh