Ачааллж байна...
Өмнөх хичээлийн төгсгөлд бид нэг асуудлыг дурдсан. Path parameter бол хүчирхэг, гэхдээ бүх зүйлд тохирдоггүй. Тэр нь заавал байх ёстой, тэр нь замын бүтцийн хэсэг байдаг, тэр нь тодорхой нэг зүйлийг заадаг.
Гэтэл API-д ихэвчлэн өөр төрлийн утга хэрэгтэй болдог: заавал биш, нэмэлт, тохируулга шинжтэй утгууд. "Ном хайхдаа энэ үгээр шүү." "Эхний арваныг л өгөөч." "Огноогоор эрэмбэлээд өгөөч." Эдгээрийг замд шахах нь утгагүй — тэдгээр нь замын нэг хэсэг биш, харин хүсэлтийн тохируулга юм.
Тэдгээрт зориулсан механизм бол query parameter. Та түүнийг өдөр бүр хардаг байсан, зүгээр л нэрийг нь мэддэггүй байсан.
Интернэтэд ямар нэг зүйл хайхад хаягийн мөр ойролцоогоор ийм харагддаг:
https://www.example.com/search?q=python&page=2Асуултын тэмдгийн (?) дараах бүх зүйл бол query parameter юм. Тэднийг задалж харъя.
? — энэ тэмдэг замын төгсгөл, параметрүүдийн эхлэлийг заана. Түүнээс өмнөх хэсэг (/search) бол зам; түүнээс хойших хэсэг бол параметрүүд.
q=python — эхний параметр. q бол нэр, python бол утга, тэнцүүгийн тэмдэг тэдгээрийг холбож байна.
& — олон параметрийг хооронд нь салгах тэмдэг.
page=2 — хоёр дахь параметр.
Тэгэхээр энэ хаяг ингэж уншигдана: "/search гэсэн хуудас руу оч. q гэсэн тохируулгад python гэсэн утга өг. page гэсэн тохируулгад 2 гэсэн утга өг."
Энэ бүтцийг санаж авах хамгийн энгийн арга: эхний параметрийн өмнө ?, дараагийн бүрийн өмнө &. Гурав дахь параметр нэмэх бол дахиад & тавина.
Зоогийн газрын зүйрлэлээ үргэлжлүүлье. Path parameter бол аль хоол гэдгийг заадаг: "17-р хоол." Тэр нь заавал байх ёстой — зөөгч аль хоол гэдгийг мэдэхгүй бол ажиллаж чадахгүй.
Query parameter бол тэр хоолыг хэрхэн гэдгийг заадаг: "давсгүй", "хоёр хувь", "халуун ногоотой". Эдгээр нь заавал биш. Зочин юу ч хэлэхгүй бол зөөгч ердийн хэлбэрээр авчирна. Гэхдээ хэлбэл зөөгч тохируулж өгнө.
Тиймээс дүрэм энгийн: тодорхой юмыг заадаг бол path, тохируулга бол query.
main.py файлаа дараах кодоор солино:
python
# main.py
from fastapi import FastAPI
app = FastAPI(title="Номын API")
books = [
{"id": 1, "title": "Монголын нууц товчоо", "year": 1240},
{"id": 2, "title": "Цог хийморь", "year": 1962},
{"id": 3, "title": "Цагаан хэрэм", "year": 1971},
{"id": 4, "title": "Хөх судар", "year": 1971},
{"id": 5, "title": "Тунгалаг тамир", "year": 1962},
]
@app.get("/books")
def get_books(limit: int = 10):
return books[:limit]Анзаараарай: books одоо dictionary биш, list болсон. Энэ хичээлд жагсаалт дээр ажиллах нь илүү тохиромжтой.
Хадгална. Reload болсныг шалгана.
Кодын задаргаа
python
def get_books(limit: int = 10):Энэ мөрөнд гурван зүйл байна. limit бол параметрийн нэр. int бол type hint. = 10 бол default утга.
Одоо хамгийн чухал асуулт: FastAPI яаж мэдэв энэ нь query parameter гэдгийг? Хариу нь маш энгийн бөгөөд гоё:
Функцийн параметрийн нэр замын дөрвөлжин хаалтад байвал — path parameter. Байхгүй бол — query parameter.
Энд замд (/books) ямар ч дөрвөлжин хаалт байхгүй. Тиймээс limit нь query parameter болно. FastAPI үүнийг таамаглаагүй, зөвхөн харьцуулж үзсэн.
= 10 гэсэн default утга нь энэ параметр заавал биш гэдгийг хэлж байна. Хэрэглэгч юу ч хэлэхгүй бол 10 гэж үзнэ. Курс 2-ын Бүлэг 3-т та функцийн default утгыг сурсан; яг тэр зүйл, зөвхөн одоо вэб хаягтай холбогдож байна.
books[:limit] бол Курс 2-ын Бүлэг 2-ын slicing — жагсаалтын эхний limit элементийг авна.
Параметргүй хүсэлт
http://127.0.0.1:8000/booksХариу:
json
[{"id":1,"title":"Монголын нууц товчоо","year":1240},{"id":2,"title":"Цог хийморь","year":1962},{"id":3,"title":"Цагаан хэрэм","year":1971},{"id":4,"title":"Хөх судар","year":1971},{"id":5,"title":"Тунгалаг тамир","year":1962}]Таван ном бүгд ирлээ. Хэрэглэгч limit өгөөгүй тул default утга (10) хэрэгжсэн. books[:10] гэдэг нь таван элементтэй жагсаалтад бүхэлд нь гэсэн үг — slicing жагсаалтын уртаас хэтэрсэн ч алдаа өгдөггүй, зүгээр л байгаа бүхнийг өгдөг.
Параметртэй хүсэлт
http://127.0.0.1:8000/books?limit=2Хариу:
json
[{"id":1,"title":"Монголын нууц товчоо","year":1240},{"id":2,"title":"Цог хийморь","year":1962}]Хоёр ном ирлээ. Хэрэглэгч limit=2 гэж хэлсэн, FastAPI тэр текстийг барьж аваад, int болгож хувиргаад, функцэд дамжуулсан.
Дахин анзаараарай: хаягны бүх зүйл текст байдаг. 2 гэдэг нь "2" байсан. Type hint нь түүнийг тоо болгосон. Path parameter дээр ажиллаж байсан яг тэр механизм энд ч ажиллаж байна.
Буруу утга илгээвэл
http://127.0.0.1:8000/books?limit=abcХариу (статус 422):
json
{
"detail": [
{
"type": "int_parsing",
"loc": [
"query",
"limit"
],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "abc"
}
]
}Өмнөх хичээлд уншсан бүтэц яг ижилхэн. Гэхдээ нэг ялгаа бий, түүнийг олж хараарай:
json
"loc": ["query", "limit"]Өмнө нь "path" байсан. Одоо "query" байна. FastAPI алдаа хаана гарсныг яг зөв хэлж байна — замд биш, асуултын тэмдгийн ард. Энэ жижиг ялгаа нь олон параметртэй том API дээр асар их цаг хэмнэдэг.
Хайлтын параметр нэмье:
python
# main.py
from fastapi import FastAPI
app = FastAPI(title="Номын API")
books = [
{"id": 1, "title": "Монголын нууц товчоо", "year": 1240},
{"id": 2, "title": "Цог хийморь", "year": 1962},
{"id": 3, "title": "Цагаан хэрэм", "year": 1971},
{"id": 4, "title": "Хөх судар", "year": 1971},
{"id": 5, "title": "Тунгалаг тамир", "year": 1962},
]
@app.get("/books")
def get_books(search: str = "", limit: int = 10):
result = books
if search:
result = [b for b in result if search.lower() in b["title"].lower()]
return result[:limit]search: str = "" — хоосон текст нь default. Хэрэглэгч юу ч хайхгүй бол хоосон утга ирнэ, if search: нөхцөл худал болно, шүүлт хийгдэхгүй.
Дотор нь list comprehension байна — Курс 2-ын Бүлэг 2. .lower() хоёр талдаа хэрэглэсэн нь том жижиг үсгийн ялгааг арилгаж байна, ингэснээр "ЦОГ" гэж хайсан ч "Цог хийморь" олдоно.
Хүсэлт
http://127.0.0.1:8000/books?search=цагХариу:
json
[{"id":3,"title":"Цагаан хэрэм","year":1971}]"цаг" гэсэн үг зөвхөн "Цагаан хэрэм" дотор байна.
Хоёр параметр хамт
http://127.0.0.1:8000/books?search=ц&limit=2Хариу:
json
[{"id":2,"title":"Цог хийморь","year":1962},{"id":3,"title":"Цагаан хэрэм","year":1971}]"ц" үсэг гурван номын нэрэнд байгаа боловч limit=2 тул зөвхөн хоёр нь ирлээ. Хоёр параметр хамтдаа ажиллаж байна — эхлээд шүүлт, дараа нь хязгаарлалт.
Хаягны бүтцийг ажиглаарай: ?search=ц дараа нь &limit=2. Эхнийх нь асуултын тэмдэгтэй, хоёр дахь нь амперсандтай.
Дараалал хамаагүй. ?limit=2&search=ц гэж бичсэн ч яг ижил үр дүн гарна. FastAPI параметрийг нэрээр нь олдог, байрлалаар нь биш.
Query parameter нь bool төрөлтэй ч байж болно, энэ нь маш ашигтай:
python
# main.py (get_books функцийг солино)
@app.get("/books")
def get_books(search: str = "", limit: int = 10, newest_first: bool = False):
result = books
if search:
result = [b for b in result if search.lower() in b["title"].lower()]
if newest_first:
result = sorted(result, key=lambda b: b["year"], reverse=True)
return result[:limit]lambda — Курс 2-ын Бүлэг 3-аас. sorted() функцэд "юугаар эрэмбэлэх вэ" гэдгийг хэлж байна: ном бүрийн year талбараар.
Хүсэлт
http://127.0.0.1:8000/books?newest_first=true&limit=3Хариу:
json
[{"id":3,"title":"Цагаан хэрэм","year":1971},{"id":4,"title":"Хөх судар","year":1971},{"id":2,"title":"Цог хийморь","year":1962}]Хамгийн шинэ гурван ном, огноогоор буурахаар эрэмбэлэгдсэн.
bool утгыг хэрхэн бичих вэ
Энд нэг сонирхолтой зүйл байна. Хаяг бол текст, тэнд Python-ы True гэж байдаггүй. Тэгвэл FastAPI юуг үнэн гэж үзэх вэ?
Дараах бүх утга үнэн гэж тооцогдоно:
?newest_first=true
?newest_first=True
?newest_first=1
?newest_first=on
?newest_first=yesДараах бүх утга худал гэж тооцогдоно:
?newest_first=false
?newest_first=False
?newest_first=0
?newest_first=off
?newest_first=noFastAPI (яг хэлбэл Pydantic) эдгээрийг бүгдийг ойлгодог. Энэ нь тав тухтай, учир нь өөр өөр программ өөр өөр хэлбэрээр илгээдэг.
Харин ?newest_first=magadgui гэвэл 422 гарна:
json
{
"detail": [
{
"type": "bool_parsing",
"loc": [
"query",
"newest_first"
],
"msg": "Input should be a valid boolean, unable to interpret input",
"input": "magadgui"
}
]
}type талбар нь одоо bool_parsing — өмнөх int_parsing биш. Алдааны төрөл өөрчлөгдсөн боловч бүтэц яг ижилхэн. Нэг удаа энэ бүтцийг ойлгосон бол бүх төрлийн validation алдааг уншиж чадна.
/docs хуудсаа нээж, GET /books дээр товшино.
Parameters хэсэгт одоо гурван мөр байна:
search string (query) Default: ""
limit integer (query) Default: 10
newest_first boolean (query) Default: falseХэд хэдэн зүйлийг анзаараарай.
Аль нь ч required гэж тэмдэглэгдээгүй — учир нь бүгд default утгатай. Өмнөх хичээлийн book_id дээр од (*) байсныг санаж байна уу? Энд байхгүй.
Төрөл бүр зөв харагдаж байна: string, integer, boolean. Таны type hint-ээс шууд ирсэн.
Default утга бүр харагдаж байна. Хэрэглэгч юу ч оруулахгүй бол юу болохыг баримт бичиг өөрөө хэлж байна.
Try it out дарахад newest_first талбар нь энгийн текст талбар биш, харин сонголтын жагсаалт (dropdown) болж харагдана: true / false. Swagger UI энэ нь boolean гэдгийг мэдэж байгаа тул тохирсон хэрэгсэл өгсөн. Дахин хэлэхэд: та ямар ч нэмэлт ажил хийгээгүй.
Query parameter заавал биш байх нь ердийн зүйл. Гэхдээ заавал болгож болно — зүгээр л default утга өгөхгүй:
python
@app.get("/search")
def search_books(q: str):
return [b for b in books if q.lower() in b["title"].lower()]q: str — default байхгүй.
Хүсэлт (параметргүй):
http://127.0.0.1:8000/searchХариу (статус 422):
json
{
"detail": [
{
"type": "missing",
"loc": [
"query",
"q"
],
"msg": "Field required",
"input": null
}
]
}Шинэ алдааны төрөл: missing. Мессеж нь Field required — "энэ талбар заавал". input нь null, учир нь юу ч ирээгүй.
Хүсэлт (параметртэй):
http://127.0.0.1:8000/search?q=хэрэмХариу:
json
[{"id":3,"title":"Цагаан хэрэм","year":1971}]Тэгэхээр дүрэм маш энгийн: default утга байвал заавал биш, байхгүй бол заавал. Энэ бол Python-ы функцийн ердийн дүрэм; FastAPI зүгээр л түүнийг вэб рүү шилжүүлсэн.
Асуултын тэмдгийг мартах
http://127.0.0.1:8000/books limit=2Энэ хаяг ажиллахгүй. Query parameter эхлэхийн өмнө заавал ? тэмдэг байх ёстой.
Мөн дараагийн параметрүүдийн өмнө & тавихаа мартвал:
http://127.0.0.1:8000/books?search=ц limit=2Энэ тохиолдолд search параметрийн утга нь "ц limit=2" гэсэн бүхэл текст болно (эсвэл browser хаягийг өөрөөр тайлбарлаж алдаа өгнө). Үр дүн нь: хайлт юу ч олохгүй, limit ажиллахгүй.
Хоосон зай хаягт байх
http://127.0.0.1:8000/books?search=цог хийморьХаягт хоосон зай байж болохгүй. Browser ихэвчлэн үүнийг өөрөө засаж, хоосон зайг %20 эсвэл + болгож хувиргадаг:
http://127.0.0.1:8000/books?search=цог%20хийморьЭнэ бол URL encoding гэдэг зүйл. Browser болон FastAPI хоёулаа үүнийг мэддэг тул ихэнх тохиолдолд та санаа зовох шаардлагагүй — таны функцэд "цог хийморь" гэсэн хэвийн текст ирнэ. Гэхдээ хаягийн мөрөнд хачин тэмдэгт харвал энэ нь юу болохыг мэдэж байх нь зүйтэй.
Кирилл үсэг ч мөн адил кодлогддог. Хаягийг хуулж авахад %D1%86%D0%BE%D0%B3 гэх мэт урт зүйл харагдаж болно — тэр бол зүгээр л "цог" гэсэн үг, өөр хэлбэрээр бичигдсэн.
Хоёр параметр ижил нэртэй
python
@app.get("/books")
def get_books(limit: int = 10, limit: int = 5):
return books[:limit]Энэ бол Python-ы алдаа, FastAPI-тай ямар ч холбоогүй:
SyntaxError: duplicate argument 'limit' in function definitionНэг функцэд ижил нэртэй хоёр параметр байж болохгүй.
Хүсвэл year гэсэн query parameter нэмж, тодорхой оны номуудыг шүүж үзээрэй. Жишээ нь:
python
@app.get("/books")
def get_books(year: int = 0):
if year:
return [b for b in books if b["year"] == year]
return booksДараа нь /books?year=1971 гэж хандаж үзээрэй. Хоёр ном ирэх ёстой.
Сонирхвол /docs хуудсан дээр Try it out дарж, талбаруудыг хоосон орхиод Execute дарж үзээрэй. Дараа нь дээд талд гарч ирэх Request URL-ийг ажиглаарай — Swagger UI хоосон талбаруудыг хаягт огт оруулаагүй байхыг та харна. Энэ нь "заавал биш" гэдэг нь юу гэсэн үг болохыг тодорхой харуулна.
Query parameter — хаягны ? тэмдгийн ард ирэх нэмэлт утгууд: ?search=ц&limit=2.
Эхний параметрийн өмнө ?, дараагийн бүрийн өмнө &.
FastAPI-ийн дүрэм: параметрийн нэр замын дөрвөлжин хаалтад байвал path, байхгүй бол query.
Default утга байвал заавал биш; байхгүй бол заавал (дутуу бол missing төрлийн 422).
Type hint энд ч ажиллана: хувиргалт, шалгалт, баримт бичиг.
bool параметр true/1/on/yes болон false/0/off/no зэргийг ойлгоно.
422 хариуны loc талбар "query" гэж бичигдэнэ — "path" биш.
Хаягт хоосон зай, кирилл үсэг байвал URL encoding хийгдэнэ; ихэвчлэн санаа зовох шаардлагагүй.
Одоо та хоёр төрлийн параметрийг тусад нь мэднэ. Бодит API-д тэдгээр нь ихэвчлэн хамтдаа ажилладаг: тодорхой нэг номыг зааж (path), тэр номыг хэрхэн харуулахыг тохируулна (query). Дараагийн хичээлд бид тэднийг хослуулах бөгөөд түүнчлэн нэг далд занга — route-ийн дараалал-тай холбоотой алдааг харах болно. Энэ бол шинэ хөгжүүлэгчдийг байнга гайхшруулдаг зүйл бөгөөд бид түүнийг зориудаар үүсгэж, дараа нь засна.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.