Гузариш ба мундариҷа
Мавзӯи 2 аз 6

Роҳҳо ва параметрҳо

Чаро роҳҳо ва параметрҳо лозиманд

Сомона, барномаи мобилӣ ва бот метавонанд тавассути API — қоидаҳои муошират бо сервер — аз додаҳои муштарак истифода кунанд. Муштарӣ дархости HTTP мефиристад ва сервер рамзи ҳолат ва додаҳоро бармегардонад. Масалан, феҳрист бояд дидани як китобро аз ҷустуҷӯ дар тамоми рӯйхат фарқ кунад. Роҳ захираро интихоб мекунад, параметрҳо дархостро дақиқ мекунанд.

FastAPI HTTP-ро ба функсияҳои одии Python мепайвандад: роҳ ва навъҳои вурудро тавсиф карда, луғат бармегардонем. Санҷиши додаҳо ва табдили ҷавоб ба JSON-ро фреймворк иҷро мекунад. Дар курс ин усулҳо барои рӯйхати корҳо лозим мешаванд. Ҳар мисоли поён мустақил аст: онро дар файли ҷудо сабт карда, бо Python-и курс иҷро кардан мумкин аст.

Барнома, масир ва муштарӣ

FastAPI() барномаро месозад. Масир усули HTTP ва роҳро якҷо мекунад: GET / хондани захираи решагӣ аст. Декоратори @app.get функсияро сабт мекунад, вале фавран даъват намекунад. TestClient дархостро бе сервери ҷудои шабакавӣ рост ба барнома мефиристад. status_code адад аст, json() додаҳои таҷзияшудаи ҷавобро медиҳад.

from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()

@app.get("/")
def root():
    return {"ready": True}

client = TestClient(app)
r = client.get("/")
print(r.status_code, r.json())
print(client.get("/docs").status_code)

Баромад:

200 {'ready': True}
200

Параметри роҳ ва табдили навъ

Қавсҳои фигурӣ қисми тағйирёбандаи роҳро ҷудо мекунанд. Номи он бояд бо параметри функсия мувофиқ бошад. Аннотатсияи int аз FastAPI талаб мекунад, ки матни URL-ро ба адади бутун табдил диҳад. Адади 7 ва сатри "7", масалан ҳамчун калиди луғат, фарқ мекунанд. Матни номувофиқ пеш аз даъвати функсия 422 мегирад; роҳи номаълум 404 медиҳад.

from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()

@app.get("/books/{book_id}")
def book(book_id: int):
    return {"next": book_id + 1}

client = TestClient(app)
print(client.get("/books/7").json())
print(client.get("/books/abc").status_code)
print(client.get("/unknown").status_code)

Баромад:

{'next': 8}
422
404

Query: пешфарз ва ҳудудҳо

Параметрҳои пас аз ? query-параметр ном доранд. Чанд ҷуфтро бо & мепайванданд. FastAPI одатан параметри одии дар роҳ набударо аз он ҷо мегирад. Қимати пешфарз имкон медиҳад, ки онро нафиристед. Query маҳдудият меафзояд: ge ҳудуди поёнӣ ва le ҳудуди болоиро дар бар мегиранд; gt ва lt худи ҳудудро истисно мекунанд. Ин санҷиши вуруд аст, на буридани қимат.

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

app = FastAPI()

@app.get("/batch")
def batch(size: int = Query(2, ge=1, le=4)):
    return list(range(size))

client = TestClient(app)
print(client.get("/batch").json())
print(client.get("/batch?size=4").json())
print(client.get("/batch?size=0").status_code)

Баромад:

[0, 1]
[0, 1, 2, 3]
422

Набудани қимат, сатри холӣ ва False

None барои ҳолати алоҳидаи «филтр дода нашуд» қулай аст. Навъи bool | None қимати мантиқӣ ё None-ро иҷозат медиҳад, = None бошад, партофтани параметрро мумкин мекунад. Бе пешфарз параметр ҳатмӣ мемонад. false, 0 ва no ба False табдил меёбанд. Санҷиши is None набуданро аз False-и ошкоро додашуда фарқ мекунад; сатри холӣ низ аз параметри набуда фарқ дорад.

from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()

@app.get("/filter")
def filters(active: bool | None = None, q: str | None = None):
    return {"active": active, "q": q}

client = TestClient(app)
print(client.get("/filter").json())
print(client.get("/filter?active=no&q=").json())
print(client.get("/filter?active=maybe").status_code)

Баромад:

{'active': None, 'q': None}
{'active': False, 'q': ''}
422

Хатои барнома

Навъи дуруст маънои дастрас будани захираро надорад. HTTPException радкунии пешбинишудаи барномаро тавсиф мекунад. Онро бо raise ба вуҷуд меоранд: иҷрои масир қатъ шуда, detail ба JSON меравад. Мисол дастрасиро аз рӯйи рақам маҳдуд мекунад; он ҳалли масъалаҳои курсро намедиҳад.

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

app = FastAPI()

@app.get("/shelves/{number}")
def shelf(number: int):
    if number < 1:
        raise HTTPException(404, detail={"number": number})
    return {"number": number}

client = TestClient(app)
r = client.get("/shelves/0")
print(r.status_code, r.json())

Баромад:

404 {'detail': {'number': 0}}

Дар дохил чӣ рӯй медиҳад

Пештахтаи хизматрасониро тасаввур кунед: корманд аввал аз рӯйи усул ва роҳ равзанаи лозимро интихоб мекунад, баъд варақаро месанҷад. FastAPI масирро муайян карда, қиматҳои роҳ ва query-ро мегирад ва тавассути Pydantic месанҷаду табдил медиҳад. Функсия танҳо пас аз санҷиши муваффақ даъват мешавад. Натиҷа ба ҷавоб табдил меёбад; HTTPException алоҳида коркард мешавад. Аз ин рӯ, 422 ҳатто бе ягон if дар функсия пайдо шуда метавонад.

Барои сервери воқеӣ барномаро ҳамчун main.py сабт карда, uvicorn main:app --reload-ро иҷро кунед. Дар ин ҷо main номи модул ва app объекти барнома аст; --reload ҳангоми таҳия қулай мебошад. /docs Swagger UI-ро нишон медиҳад ва /openapi.json API-ро тавсиф мекунад. TestClient ҳамон барномаро бе гӯш кардани порт месанҷад.

Хатоҳои маъмул ва ислоҳи онҳо

  1. def book(book_id: str) рақамро сатр мемонад: он бо калидҳои ададӣ мувофиқ намеояд. Агар шартнома рақам талаб кунад, int эълон кунед.
  2. size: int = 0 ҳудуди поёнӣ намегузорад: сифр иҷозат аст. Барои андозаи мусбат Query(..., ge=1) ва пешфарзи дуруст илова кунед.
  3. if active: қимати False ва набудани филтрро омехта мекунад. Аввал active is None-ро санҷед, баъд ҳар ду қимати мантиқиро коркард кунед.
  4. return HTTPException(404) ба ҷойи ба вуҷуд овардани хато объект бармегардонад. raise HTTPException(404) истифода кунед.

Ёддошт

Мақсад Навишт
Сабти масири хондан @app.get("/path")
Гирифтани адад аз роҳ "/{number}" ва number: int
Маҳдуд кардани query Query(2, ge=1, le=4)
Иҷозати нафиристодан T | None = None
Қатъи дархост raise HTTPException(code, detail=...)
Санҷидани ҷавоб client.get(...), r.status_code, r.json()