Ачааллж байна...
Өмнөх бүлэгт бид @app.post гэсэн decorator-ыг хэд хэдэн удаа ашигласан, гэхдээ түүнийг тайлбарлаагүй. "Өгөгдөл хүлээж авах endpoint нь GET биш" гэж хэлээд өнгөрсөн. Одоо тэр өрийг төлье.
Энэ хичээл голдуу ойлголтын тухай. Бид код бага бичнэ. Оронд нь HTTP method гэж юу болох, GET болон POST юугаараа ялгаатай, яагаад энэ ялгаа чухал болохыг ойлгоно. Энэ ойлголт нь дараагийн хичээлүүдийн суурь болно — POST, PUT, DELETE бүгд энэ дээр тулгуурлана.
Курс 2-ын Бүлэг 11-т та HTTP-тэй танилцсан. Богино сануулга: интернэт дээр программууд хоорондоо хүсэлт (request) болон хариу (response)-аар харьцдаг. Хүсэлт бүр хоёр үндсэн зүйлтэй: хаяг (хаашаа) болон method (юу хийх гэж байгаа).
Method бол хүсэлтийн зорилго юм. Ижил хаяг руу өөр өөр method-оор хандаж, өөр өөр зүйл хийж болно. Жишээ нь /books/2 гэсэн хаяг руу:
GET хийвэл — тэр номыг унших
PUT хийвэл — тэр номыг засах
DELETE хийвэл — тэр номыг устгах
Ижил хаяг, гурван өөр үйлдэл. Method нь ялгааг гаргаж байна.
Энэ бол ухаалаг зохион байгуулалт. Хаяг нь юуг заадаг (аль ном), method нь юу хийхийг заадаг (унших/засах/устгах). Хоёрыг хослуулж, цөөн хаягаар олон үйлдэл илэрхийлдэг.
HTTP-д хэд хэдэн method байдаг. Энэ сургалтад бид дөрвийг ашиглана. Тэдгээрийг нэг дор танилцуулъя, дараа нь тус бүрт нь хичээл зориулна.
GET — унших. Өгөгдөл авах. Юу ч өөрчлөхгүй. Бид Түвшин 1 бүхэлдээ GET ашигласан.
POST — үүсгэх. Шинэ зүйл нэмэх. Жишээ нь шинэ ном бүртгэх.
PUT — засах. Байгаа зүйлийг өөрчлөх. Жишээ нь номын мэдээллийг шинэчлэх.
DELETE — устгах. Зүйлийг арилгах. Жишээ нь номыг бүртгэлээс хасах.
Эдгээр дөрвийг англиар CRUD гэж товчилдог: Create (POST), Read (GET), Update (PUT), Delete (DELETE). Энэ бол өгөгдөлтэй хийж болох дөрвөн үндсэн үйлдэл бөгөөд бараг бүх API эдгээрээс бүрддэг. Бид Бүлэг 5-6-д CRUD-ыг бүрэн эзэмшинэ.
Зоогийн газрын зүйрлэлээ өргөтгөе. Цэс (API) дээр зочин дөрвөн төрлийн зүйл хийж болно.
GET — цэс харах, хоол асуух. Зочин "ямар хоол байна?" эсвэл "17-р хоол юунаас бүрддэг вэ?" гэж асууна. Юу ч өөрчлөгддөггүй, зөвхөн мэдээлэл авдаг.
POST — шинэ захиалга өгөх. Зочин "нэг хуушуур авъя" гэж захиална. Шинэ зүйл үүсдэг — өмнө байгаагүй захиалга.
PUT — захиалгаа өөрчлөх. Зочин "хуушуураа шарсан талх болгож өөрчилье" гэнэ. Байгаа захиалга шинэчлэгдэнэ.
DELETE — захиалга цуцлах. Зочин "захиалгаа болиулъя" гэнэ. Байгаа зүйл арилна.
Зөөгч эдгээрийг ялгаж ойлгодог. "Асуух" болон "захиалах" хоёр өөр үйлдэл. Хэрэв зочин зүгээр л "хуушуур" гэж хэлбэл зөөгч эргэлзэнэ — асууж байна уу, захиалж байна уу? Method нь тэр эргэлзээг арилгадаг.
Хоёр method-ыг гүнзгий харьцуулъя, учир нь энэ хоёр хамгийн түгээмэл.
1. Зорилго
GET унших зорилготой. Сервер дээрх зүйлийг өөрчлөхгүй. Хэдэн ч удаа GET хийсэн ижил үр дүн — өгөгдөл хэвээр.
POST үүсгэх зорилготой. Сервер дээр шинэ зүйл нэмнэ. Хоёр удаа POST хийвэл хоёр шинэ зүйл үүснэ.
2. Өгөгдөл хаана явах
GET-ийн өгөгдөл хаягт байна. Бүлэг 2-т үзсэнчлэн — path parameter, query parameter. Богино, энгийн утга.
POST-ийн өгөгдөл body-д байна. Бүлэг 4-т үзсэнчлэн — request body, JSON хэлбэрээр. Урт, бүтэцтэй өгөгдөл.
Яагаад энэ ялгаа? Учир нь та шинэ ном үүсгэхэд түүний бүх мэдээллийг (нэр, зохиолч, он, тайлбар) илгээх ёстой. Тэр бүхэн хаягт багтахгүй. Body нь хязгааргүй том, бүтэцтэй өгөгдөл зөөж чадна.
3. Харагдах байдал
GET-ийн өгөгдөл хаягт харагдана. Browser-ийн түүхэнд хадгалагдана, log-д бичигдэнэ, хуваалцахад хялбар. Тиймээс GET-ээр нууц зүйл (нууц үг) илгээж болохгүй.
POST-ийн өгөгдөл body-д нуугдана. Хаягт харагдахгүй, түүхэнд үлдэхгүй. Тиймээс нууц үг, хувийн мэдээлэл POST-оор явдаг.
(Анхаар: body нь нуугдсан гэдэг нь шифрлэгдсэн гэсэн үг биш. Жинхэнэ аюулгүй байдалд HTTPS хэрэгтэй — тэр нь бүх өгөгдлийг шифрлэдэг. Гэхдээ энэ сургалтын хүрээнээс гадуур.)
4. Browser-аас туршиж болох эсэх
GET-ийг хаягийн мөрөөр туршиж болно. Browser-ийн хаягийн мөрөнд хаяг бичиж Enter дарах нь GET хүсэлт юм. Тиймээс бид Түвшин 1-д ихэнх зүйлээ хаягийн мөрөөр туршсан.
POST-ийг хаягийн мөрөөр туршиж болохгүй. Хаягийн мөр зөвхөн GET илгээдэг, body явуулж чаддаггүй. Тиймээс POST-ыг /docs (эсвэл requests код)-оор туршина.
GET | POST | |
|---|---|---|
Зорилго | Унших | Үүсгэх |
Өгөгдөл хаана | Хаягт (path/query) | Body-д (JSON) |
Сервер өөрчлөгдөх үү | Үгүй | Тийм |
Хаягт харагдах уу | Тийм | Үгүй |
Хаягийн мөрөөр турших | Болно | Болохгүй |
Status code (амжилт) | 200 | 201 |
Сүүлийн мөрийг анзаараарай. Бүлэг 3-т сурсанчлан GET амжилттай бол 200, POST амжилттай бол 201 (Created) буцаадаг — учир нь POST шинэ зүйл үүсгэсэн.
Одоо жижиг жишээгээр хоёр method-ыг зэрэгцүүлж харъя. main.py файлаа дараах кодоор солино:
python
# main.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(title="Тэмдэглэлийн API")
notes = []
class Note(BaseModel):
text: str
@app.get("/notes")
def get_notes():
return notes
@app.post("/notes", status_code=201)
def create_note(note: Note):
notes.append(note.text)
return {"message": "Тэмдэглэл нэмэгдлээ", "text": note.text}Хадгална.
Кодын задаргаа
notes = [] — тэмдэглэлүүдийг хадгалах хоосон жагсаалт. Одоохондоо санах ойд — сервер унтраахад алга болно.
Note model — ганц талбартай, text.
get_notes — GET, бүх тэмдэглэлийг унших. notes.append(...) байхгүй; зөвхөн буцаана. Юу ч өөрчлөхгүй.
create_note — POST, шинэ тэмдэглэл үүсгэх. note: Note тул body-оос өгөгдөл авна. notes.append(note.text) — жагсаалтад нэмнэ, өөрчилнэ. status_code=201 — үүсгэсэн тул 201.
Хоёр функцийн ялгааг харна уу: GET зөвхөн уншина, POST өөрчилнө. Энэ бол дээр ярьсан "зорилгын ялгаа"-ийн бодит код юм.
Эхлээд GET — хоосон
http://127.0.0.1:8000/notesЭнэ бол GET тул хаягийн мөрөөр туршиж болно.
Хариу (статус 200):
json
[]Хоосон жагсаалт — одоохондоо тэмдэглэл алга.
Дараа нь POST — нэмэх
Одоо /docs руу орно (POST тул хаягийн мөр ажиллахгүй). POST /notes -> Try it out. JSON-ыг солино:
json
{
"text": "Сүү авах"
}Execute дарна.
Server response (статус 201):
json
{
"message": "Тэмдэглэл нэмэгдлээ",
"text": "Сүү авах"
}Status code 201 гэдгийг анзаараарай — 200 биш. Шинэ зүйл үүссэн.
Дахин POST хийж, өөр тэмдэглэл нэмнэ:
json
{
"text": "Номоо буцаах"
}Эцэст нь GET дахин — өөрчлөгдсөн
Одоо browser дээр дахин:
http://127.0.0.1:8000/notesХариу (статус 200):
json
["Сүү авах","Номоо буцаах"]Өөрчлөгдсөн. Эхлээд хоосон байсан жагсаалт одоо хоёр тэмдэглэлтэй.
Юу болсныг ажиглаарай. POST хийх бүрд жагсаалт өөрчлөгдсөн — шинэ зүйл нэмэгдсэн. GET хийхэд жагсаалт өөрчлөгдөөгүй — зөвхөн уншсан. Хэдэн ч удаа GET хийсэн ижил хоёр тэмдэглэл ирнэ. Дахин POST хийвэл гурав дахь нэмэгдэнэ.
Энэ бол GET болон POST хоёрын гол ялгааны бодит илрэл: POST өөрчилдөг, GET өөрчилдөггүй.
Нэг чухал ойлголтыг тодруулъя. GET-ийг хэдэн ч удаа хийж болно, ямар ч гэм хоргүй. Хуудсаа арван удаа шинэчлэхэд ижил өгөгдөл арван удаа ирнэ, юу ч өөрчлөгдөхгүй.
Гэхдээ POST-ыг давтахад давхардал үүсдэг. Хэрэв та /docs дээр ижил тэмдэглэлийг гурван удаа Execute дарвал гурван ижил тэмдэглэл нэмэгдэнэ.
Энэ нь бодит амьдралд асуудал үүсгэдэг. Хэрэглэгч "нэмэх" товч дараад, интернэт удаашрахад дахин дардаг — тэгвэл хоёр ижил захиалга үүсдэг. Энэ асуудлыг шийдэх аргууд байдаг (жишээ нь давхардлыг шалгах), гэхдээ энэ сургалтын хүрээнээс гадуур. Одоохондоо энэ зан төлөвийг мэдэж байх нь хангалттай: POST давтагдвал давхардана.
Бид дараагийн хичээл (PUT ба DELETE)-д idempotency гэсэн ойлголтоор энэ сэдэвт эргэн орно.
"Би бүх зүйлээ POST-оор хийж болох уу? Эсвэл бүгдийг GET-ээр?" гэсэн асуулт гарч болно. Техникийн хувьд заримыг нь хийж болно. Гэхдээ буруу юм. Гурван шалтгаанаар.
Нэгд, бусад хөгжүүлэгч ойлгохгүй. HTTP method бол дэлхий нийтийн стандарт. Хүн таны API-г хараад "GET /books бол уншина, POST /books бол үүсгэнэ" гэдгийг тайлбаргүйгээр ойлгодог. Хэрэв та бүгдийг POST-оор хийвэл тэр стандарт эвдэрч, хүн бүр таны кодыг тусад нь судлах ёстой болно.
Хоёрт, хэрэгслүүд бутарна. Browser, proxy, cache зэрэг олон хэрэгсэл method-ийн утгад найддаг. Жишээ нь GET-ийн үр дүнг cache хийж болдог (учир нь өөрчлөгддөггүй), гэхдээ POST-ыг хийж болохгүй. Хэрэв та уншилтыг POST-оор хийвэл эдгээр оновчлол ажиллахгүй.
Гуравт, аюулгүй байдал. Зарим систем "GET нь аюулгүй, POST нь болгоомжтой" гэсэн таамаглал дээр баригдсан байдаг. Хэрэв та өгөгдөл устгах үйлдлийг GET-ээр хийвэл (жишээ нь /books/2/delete), search engine эсвэл browser-ийн урьдчилсан ачаалалт тэр хаягийг санамсаргүй дуудаж, өгөгдлийг устгаж болзошгүй.
Дүрэм: method-ийн утгыг хүндэл. Уншвал GET. Үүсгэвэл POST. Засвал PUT. Устгавал DELETE. Энэ нь зөвлөмж биш, дэлхий нийтийн гэрээ юм.
GET руу POST илгээх (эсвэл эсрэгээр)
/docs дээр POST /notes endpoint байхад, хэрэв та ижил хаяг руу GET хүсэлт (жишээ нь browser-ийн хаягийн мөрөөр) POST өгөгдөлтэй илгээх гэвэл method таарахгүй.
Хэрэв огт бүртгэлгүй хослол руу хандвал (жишээ нь PUT /notes — хараахан бичээгүй):
Хариу (статус 405):
json
{
"detail": "Method Not Allowed"
}Шинэ status code: 405 (Method Not Allowed). Энэ нь "тийм хаяг байгаа, гэхдээ тэр method-ыг дэмждэггүй" гэсэн үг. /notes хаяг GET болон POST-ыг мэднэ, гэхдээ PUT-ыг мэдэхгүй.
Энэ нь 404-өөс ялгаатай: 404 бол "тийм хаяг байхгүй", 405 бол "хаяг байгаа, method буруу".
POST-д body өгөхгүй
/docs дээр POST /notes Try it out хийж, JSON-ыг устгаад хоосон илгээвэл:
Server response (статус 422):
json
{
"detail": [
{
"type": "missing",
"loc": ["body", "text"],
"msg": "Field required",
...
}
]
}Бүлэг 4-өөс танил. text талбар заавал тул дутуу бол missing. loc нь ["body", "text"].
status_code мартах
python
@app.post("/notes")
def create_note(note: Note):
notes.append(note.text)
return {"message": "нэмэгдлээ"}Энэ ажиллана, гэхдээ status code нь 200 буцна — 201 биш. Алдаа биш, гэхдээ POST-ын хувьд 201 нь илүү зөв. status_code=201 нэмэх нь мэргэжлийн зан. Дараагийн хичээлүүдэд бид үүнийг тогтмол хийнэ.
Хүсвэл Note model-д нэмэлт талбар нэмээд (жишээ нь priority: str = "энгийн") туршаад үзээрэй. Заавал бус талбар нэмэхэд POST хэрхэн ажиллахыг ажиглаарай.
Сонирхвол Курс 2-ын requests мэдлэгээ ашиглан өөр терминалаас POST илгээж үзээрэй:
python
import requests
response = requests.post(
"http://127.0.0.1:8000/notes",
json={"text": "requests-ээр илгээсэн тэмдэглэл"},
)
print(response.status_code)
print(response.json())json= параметр нь body илгээж байгааг анзаараарай — Курс 2-т сурсан яг тэр зүйл. Энэ нь тойргийг бүтэн болгож байна: Курс 2-т сурсан client талын хэрэгслээр Курс 3-т бүтээж буй серверт хандаж байна.
HTTP method нь хүсэлтийн зорилгыг илэрхийлнэ; ижил хаяг руу өөр method-оор өөр үйлдэл хийж болно.
CRUD: Create (POST), Read (GET), Update (PUT), Delete (DELETE) — өгөгдлийн дөрвөн үндсэн үйлдэл.
GET унших (өөрчлөхгүй, хаягт өгөгдөл, 200); POST үүсгэх (өөрчилнө, body-д өгөгдөл, 201).
POST-ыг хаягийн мөрөөр туршиж болохгүй — /docs эсвэл requests ашиглана.
POST давтагдвал давхардана; GET-ийг хэдэн ч удаа хийж болно.
Method-ийн утгыг хүндэл — бусад хөгжүүлэгч, хэрэгсэл, аюулгүй байдал бүгд түүнд найддаг.
405 (Method Not Allowed) — хаяг байгаа, гэхдээ тэр method-ыг дэмждэггүй (404-өөс ялгаатай).
Одоо та POST яагаад оршдог, GET-ээс юугаараа ялгаатайг ойлголоо. Гэхдээ бид body хүлээж авахыг зөвхөн гүехэн харсан. Дараагийн хичээлд бид request body-г бүрэн эзэмшинэ: Pydantic model-ыг параметр болгон хэрхэн ашиглах, FastAPI body-г хэрхэн задалж, шалгаж, объект болгодог, echo-style биш жинхэнэ үүсгэх endpoint хэрхэн бичихийг гүнзгий үзнэ.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.