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

API барои рӯйхати корҳо

Аз масирҳо то API-и мукаммал

Вақте барнома хондану тағйир додани сабтҳоро меомӯзад, саволҳои нав пайдо мешаванд: кадом тарзҳои ҷобаҷогузорӣ иҷозатанд, ҷамъбастро чӣ гуна нишон диҳем ва файли калонро чӣ гуна ҷудо кунем. Мавзӯи охирин воситаҳои ташкили API-ро якҷо мекунад. Корбар новобаста аз масири интихобкардааш бояд қоидаҳои якхела гирад.

Дар ин ҷо қиматҳои маҳдуд, калиди ҷобаҷогузорӣ, ҷамъбаст ва роутерро меомӯзем. Код маҷмӯаҳои хурди берун аз рӯйхати корҳоро истифода мекунад, то усулҳоро бе ҳалли тайёри машқҳои ниҳоӣ нишон диҳад. Ҳамаи мисолҳо мустақиланд.

Literal маҷмӯи фармонҳоро маҳдуд мекунад

Literal аз typing маънои «танҳо ҳамин қиматҳо»-ро дорад. Бар хилофи str, он матни дилхоҳро қабул намекунад. FastAPI қиматро пеш аз даъвати функсия месанҷад ва /docs рӯйхати интихобҳоро нишон медиҳад. Барои маҷмӯаҳои номдор Enum низ истифода мешавад; барои қиматҳои сатрӣ синфи вориси str ва Enum қулай аст. Дар мисол режим дақиқ, бо назардошти ҳарфҳои калону хурд, интихоб мешавад.

from typing import Literal
from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()

@app.get("/view")
def view(mode: Literal["short", "full"] = "short"):
    return {"full": mode == "full"}

client = TestClient(app)
print(client.get("/view").json())
print(client.get("/view?mode=full").json())
print(client.get("/view?mode=FULL").status_code)

Баромад:

{'full': False}
{'full': True}
422

Калиди ҷобаҷогузорӣ ва ҳалли баробарӣ

sorted рӯйхати нав сохта, барои ҳар ҷузъ key-ро даъват мекунад. Калиди кортежӣ аз чап ба рост муқоиса мешавад: ҷузъи дуюм танҳо ҳангоми баробарии якум лозим аст. Манфӣ кардани адад самти як меъёрро иваз мекунад; reverse=True самти тамоми муқоисаро дигар мекунад. Дар поён аввал рӯзҳои барвақт ва дар дохили рӯз баҳои калонтар меоянд. Ин тартиб аз тартиби масъалаҳои курс фарқ мекунад.

rows = [(2, 8), (1, 3), (1, 9)]
ordered = sorted(rows, key=lambda row: (row[0], -row[1]))
print(ordered)
print(rows)
print(sorted(["b", "A", "a"], key=str.lower))

Баромад:

[(1, 9), (1, 3), (2, 8)]
[(2, 8), (1, 3), (1, 9)]
['A', 'a', 'b']

Ҷамъбаст: ҳисоб ва сериализатсия

Ҷамъбаст (aggregation) чанд сабтро ба хулосаи кӯтоҳ табдил медиҳад. sum ададҳоро ҷамъ мекунад ва Counter қиматҳои якхеларо мешуморад. Пеш аз тақсим ҳолати маҷмӯаи холиро алоҳида баррасӣ кунед. Амали // натиҷаи тақсимро ба поён гирд мекунад; барои қиматҳои ғайриманфӣ ин дар фоизҳои бутун қулай аст. Дар JSON калидҳои объект ҳамеша сатранд, ҳатто агар дар Python адад бошанд. Дар поён гурӯҳҳои баҳоро мешуморем, на фоизҳои ниҳоии корҳоро.

from collections import Counter
from fastapi import FastAPI
from fastapi.testclient import TestClient

scores = [2, 2, 5]
print(sum(scores), 8 // 3)
print(sum([]), bool([]))
app = FastAPI()

@app.get("/groups")
def groups():
    return dict(Counter(scores))

print(TestClient(app).get("/groups").json())

Баромад:

9 2
0 False
{'2': 2, '5': 1}

APIRouter масирҳои вобастаро ҷамъ мекунад

Роутер гурӯҳи масирҳоест, ки ба барнома пайваст мешавад. prefix ба ҳар роҳи маҳаллӣ илова мешавад; tags сабтҳоро дар /docs гурӯҳбандӣ мекунад, вале URL-ро тағйир намедиҳад. Аввал масирҳоро дар роутер сабт карда, баъд include_router-ро даъват мекунанд. Дар лоиҳаи калон коди роутерро дар модули ҷудо гузошта, ба файли асосӣ ворид мекунанд. Мисол дар як файл аст, то фавран иҷро шавад.

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

router = APIRouter(prefix="/library", tags=["library"])

@router.get("/count")
def count_books():
    return {"count": 3}

app = FastAPI()
app.include_router(router)
client = TestClient(app)
print(client.get("/library/count").json())
print(client.get("/count").status_code)

Баромад:

{'count': 3}
404

async def ва интизории вуруду баромад

async def функсияи асинхронӣ месозад. Дар нуқтаи await он ҳангоми интизории амали асинхронӣ метавонад иҷроро ба дархостҳои дигар диҳад. Ин бо муштарии асинхронии API ё пойгоҳи додаҳо муфид аст, вале худ аз худ ҳисобро тез намекунад. Барои мисоли такроршавандаи бе шабакаи беруна asyncio.sleep(0) истифода мекунем: он навбатро ба даври рӯйдодҳо медиҳад, на натиҷаи сохтаи шабакаро.

import asyncio
from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()

@app.get("/ready")
async def ready():
    await asyncio.sleep(0)
    return {"ready": True}

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

Баромад:

200 {'ready': True}

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

Ҳангоми пайваст кардани роутер барнома масирҳои онро бо префикс ва маълумоти иловагӣ меафзояд. Барои дархост аввал масир интихоб шуда, баъд параметрҳо санҷида, вобастагиҳо ҳисоб ва коркардкунанда иҷро мешавад. Навъи Literal дар ҳамон санҷише иштирок мекунад, ки int ё модел истифода мебаранд. Ҷобаҷогузорӣ ва ҷамъбаст амалҳои одии Python дар дохили коркардкунандаанд; FastAPI сарҳади HTTP ва сериализатсияро идора мекунад.

Коркардкунандаҳои асинхронӣ дар даври рӯйдодҳо иҷро мешаванд, FastAPI коркардкунандаҳои одии def-ро ба риштаҳои корӣ медиҳад. Даъвати боздоранда дар async def даври рӯйдодҳоро ба таъхир меандозад; ҳамтои асинхронӣ ё берун бурдани кори боздоранда лозим аст. Луғати умумии барномаи таълимӣ дар як раванд зиндагӣ карда, пас аз азнавоғозкунӣ гум мешавад. Барои додаҳои доимӣ ва чанд раванд пойгоҳи додаҳо бо тағйироти ҳамоҳангшуда лозим аст.

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

  1. mode: str ғалатнависиро ҳам мисли интихобҳои дуруст қабул мекунад. Literal[...] ё Enum-и мувофиқ истифода кунед.
  2. sorted(rows, key=..., reverse=True) меъёри дуюмро ҳам чаппа мекунад. Самтҳоро дар калиди кортежӣ алоҳида диҳед.
  3. @router.get("/library/count") бо prefix="/library" оғози роҳро такрор мекунад. Дар роутер танҳо қисми маҳаллии /count-ро нависед.
  4. Танҳо сохтани APIRouter() кофӣ нест: бе app.include_router(router) масирҳои он дар барнома дастрас намешаванд.
  5. time.sleep(1) дар async def даври рӯйдодҳоро бозмедорад. Барои таваққуфи асинхронӣ await asyncio.sleep(1) ва барои амалҳои дигар роҳи мувофиқи иҷроро истифода кунед.

Ёддошт

Мақсад Усул
Интихобҳои муайян Literal[...], Enum
Чанд меъёр key=lambda x: (first, second)
Нигоҳ доштани рӯйхати аввал sorted(...)
Ҷамъбаст sum, Counter, санҷиши додаҳои холӣ
Тақсим кардани API APIRouter(prefix=...), include_router
Интизории вуруду баромади асинхронӣ async def ва await