Parameter Path¶
"parameter" atau "variabel" path didefinisikan dengan sintaksis Python format string:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
Nilai parameter path item_id
akan dikirim ke fungsi sebagai argument item_id
:
Jika anda menjalankan contoh berikut dan kunjungi http://127.0.0.1:8000/items/foo, anda akan melihat respon:
{"item_id":"foo"}
Parameter path dengan tipe data¶
Tipe data parameter path bisa didefinisikan di dalam fungsi, menggunakan anotasi tipe data standar Python:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
Dalam hal ini item_id
didefinisikan sebagai int
.
Periksa
Penyunting kode anda bisa membantu periksa di dalam fungsi seperti pemeriksaan kesalahan, kelengkapan kode, dll.
Konversi data¶
Jika contoh berikut dijalankan dan diakses browser melalui http://127.0.0.1:8000/items/3, anda akan melihat respon:
{"item_id":3}
Periksa
Perhatikan nilai fungsi yang diterima (dan dihasilkan) adalah 3
, sebagai int
di Python, dan bukan string "3"
.
Sehingga dengan deklarasi tipe data FastAPI memberikan request otomatis "parsing".
Validasi Data¶
Tetapi jika di browser anda akses http://127.0.0.1:8000/items/foo, anda akan melihat pesan kesalahan HTTP:
{
"detail": [
{
"type": "int_parsing",
"loc": [
"path",
"item_id"
],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "foo",
"url": "https://errors.pydantic.dev/2.1/v/int_parsing"
}
]
}
Karena parameter path item_id
bernilai "foo"
yang bukan tipe data int
.
Kesalahan yang sama akan muncul jika menggunakan float
daripada int
, seperti di: http://127.0.0.1:8000/items/4.2
Periksa
Dengan deklarasi tipe data Python, FastAPI melakukan validasi data.
Perhatikan kesalahan tersebut juga menjelaskan validasi apa yang tidak sesuai.
Validasi ini sangat membantu ketika mengembangkan dan men-debug kode yang berhubungan dengan API anda.
Dokumentasi¶
Ketika anda membuka browser di http://127.0.0.1:8000/docs, anda melihat dokumentasi API interaktif otomatis berikut:
Periksa
Dengan deklarasi tipe data Python yang sama, FastAPI membuat dokumentasi interaktif otomatis (terintegrasi Swagger UI).
Perhatikan parameter path dideklarasikan sebagai integer.
Keuntungan basis-standar, dokumentasi alternatif¶
Karena skema yang dibuat berasal dari standar OpenAPI, maka banyak alat lain yang kompatibel.
Sehingga FastAPI menyediakan dokumentasi alternatif (menggunakan ReDoc), yang bisa diakses di http://127.0.0.1:8000/redoc:
Cara yang sama untuk menggunakan tools kompatibel lainnya. Termasuk alat membuat kode otomatis untuk banyak bahasa.
Pydantic¶
Semua validasi data dikerjakan di belakang layar oleh Pydantic, sehingga anda mendapatkan banyak kemudahan. Anda juga tahu proses ini akan ditangani dengan baik.
Anda bisa mendeklarasikan tipe data dengan str
, float
, bool
dan banyak tipe data kompleks lainnya.
Beberapa tipe di atas akan dibahas pada bab berikutnya tutorial ini.
Urutan berpengaruh¶
Ketika membuat operasi path, anda bisa menghadapi kondisi dimana path nya sudah tetap.
Seperti /users/me
, untuk mendapatkan data user yang sedang aktif.
Kemudian anda bisa memiliki path /users/{user_id}
untuk mendapatkan data user tertentu melalui user ID.
karena operasi path dievaluasi melalui urutan, anda harus memastikan path untuk /users/me
dideklarasikan sebelum /user/{user_id}
:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/me")
async def read_user_me():
return {"user_id": "the current user"}
@app.get("/users/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
Sebaliknya, path /users/{user_id}
juga akan sesuai dengan /users/me
, "menganggap" menerima parameter user_id
dengan nilai "me"
.
Serupa, anda juga tidak bisa mendefinisikan operasi path:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users")
async def read_users():
return ["Rick", "Morty"]
@app.get("/users")
async def read_users2():
return ["Bean", "Elfo"]
Path pertama akan selalu digunakan karena path sesuai dengan yang pertama.
Nilai terdefinisi¶
Jika ada operasi path yang menerima parameter path, tetapi anda ingin nilai valid parameter path sudah terdefinisi, anda bisa menggunakan standar Python Enum
.
Membuat class Enum
¶
Import Enum
dan buat sub-class warisan dari str
dan Enum
.
Dengan warisan dari str
dokumen API mengetahui nilai nya harus berjenis string
supaya bisa digunakan dengan benar.
Kemudian buat atribut class dengan nilai tetap string yang benar:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Info
Enumerasi (atau enum) tersedia di Python sejak versi 3.4.
Tips
"AlxexNet", "ResNet", dan "LeNet" adalah nama model Machine Learning.
Mendeklarasikan parameter path¶
Kemudian buat parameter path dengan tipe anotasi menggunakan class enum dari (ModelName
)
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Periksa dokumentasi¶
Karena nilai yang tersedia untuk parameter path telah terdefinisi, dokumen interatik bisa memunculkan:
Bekerja dengan enumarasi Python¶
Nilai parameter path akan menjadi anggota enumerasi.
Membandingkan anggota enumerasi¶
Anda bisa membandingkan parameter path dengan anggota enumerasi di enum ModelName
yang anda buat:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Mendapatkan nilai enumerasi¶
Anda bisa mendapatkan nilai (str
dalam kasus ini) menggunakan model_name.value
, atau secara umum anggota_enum_anda.value
:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Tips
Anda bisa mengakses nilai "lenet"
dnegan ModelName.lenet.value
.
Menghasilkan anggota enumerasi¶
Anda bisa menghasilkan anggota enumerasi dari operasi path bahkan di body JSON bersarang (contoh dict
).
They will be converted to their corresponding values (strings in this case) before returning them to the client:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Klien akan mendapatkan respon JSON seperti berikut:
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
Parameter path berisi path¶
Misalkan terdapat operasi path dengan path /files/{file_path}
.
Tetapi anda memerlukan file_path
itu berisi path, seperti like home/johndoe/myfile.txt
.
Sehingga URL untuk file tersebut akan seperti: /files/home/johndoe/myfile.txt
.
Dukungan OpenAPI¶
OpenAPI tidak bisa mendeklarasikan parameter path berisi path di dalamnya, karena menyebabkan kondisi yang sulit ditest dan didefinisikan.
Tetapi, di FastAPI anda tetap bisa melakukannya dengan menggunakan tools internal dari Starlette.
Dan dokumentasi tetap berfungsi walaupun tidak menambahkan keterangan bahwa parameter harus berisi path.
Konverter path¶
Melalui Starlette anda bisa mendeklarasikan parameter path berisi path dengan URL seperti:
/files/{file_path:path}
Dikondisi ini nama parameter adalah file_path
dan bagian terakhir :path
menginformasikan parameter harus sesuai dengan setiap path.
Sehingga anda bisa menggunakan:
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}
Tips
Anda mungkin perlu parameter berisi /home/johndoe/myfile.txt
di awali garis belakang (/
).
Di kondisi ini, URL nya menjadi: /files//home/johndoe/myfile.txt
, dengan dua garis belakang (//
) di antara files
dan home
.
Ringkasan¶
Di FastAPI dengan menggunakan deklarasi tipe Python standar, pendek, intuitif, anda mendapatkan:
- Dukungan editor: pemeriksaan kesalahan, autocompletion, dll.
- "Parsing" data.
- Validasi data.
- Annotasi API dan dokumentasi otomatis.
Semua itu anda hanya perlu mendeklarasikan sekali saja.
Ini adalah salah satu keunggulan FastAPI dibandingkan dengan framework lainnya (selain dari performa Python nativec)