Yol Parametreleri¶
Yol "parametrelerini" veya "değişkenlerini" Python string biçimlemede kullanılan sözdizimi ile tanımlayabilirsiniz.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
Yol parametresi olan item_id
'nin değeri, fonksiyonunuza item_id
argümanı olarak aktarılacaktır.
Eğer bu örneği çalıştırıp http://127.0.0.1:8000/items/foo sayfasına giderseniz, şöyle bir çıktı ile karşılaşırsınız:
{"item_id":"foo"}
Tip İçeren Yol Parametreleri¶
Standart Python tip belirteçlerini kullanarak yol parametresinin tipini fonksiyonun içerisinde tanımlayabilirsiniz.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
Bu durumda, item_id
bir int
olarak tanımlanacaktır.
Ek bilgi
Bu sayede, fonksiyon içerisinde hata denetimi, kod tamamlama gibi konularda editör desteğine kavuşacaksınız.
Veri Dönüşümü¶
Eğer bu örneği çalıştırıp tarayıcınızda http://127.0.0.1:8000/items/3 sayfasını açarsanız, şöyle bir yanıt ile karşılaşırsınız:
{"item_id":3}
Ek bilgi
Dikkatinizi çekerim ki, fonksiyonunuzun aldığı (ve döndürdüğü) değer olan 3
bir string "3"
değil aksine bir Python int
'idir.
Bu tanımlamayla birlikte, FastAPI size otomatik istek "ayrıştırma" özelliği sağlar.
Veri Doğrulama¶
Eğer tarayıcınızda http://127.0.0.1:8000/items/foo sayfasını açarsanız, şuna benzer güzel bir HTTP hatası ile karşılaşırsınız:
{
"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"
}
]
}
Çünkü burada item_id
yol parametresi int
tipinde bir değer beklerken "foo"
yani string
tipinde bir değer almıştı.
Aynı hata http://127.0.0.1:8000/items/4.2 sayfasında olduğu gibi int
yerine float
bir değer verseydik de ortaya çıkardı.
Ek bilgi
Böylece, aynı Python tip tanımlaması ile birlikte, FastAPI veri doğrulama özelliği sağlar.
Dikkatinizi çekerim ki, karşılaştığınız hata, doğrulamanın geçersiz olduğu mutlak noktayı da açık bir şekilde belirtiyor.
Bu özellik, API'ınızla iletişime geçen kodu geliştirirken ve ayıklarken inanılmaz derecede yararlı olacaktır.
Dokümantasyon¶
Ayrıca, tarayıcınızı http://127.0.0.1:8000/docs adresinde açarsanız, aşağıdaki gibi otomatik ve interaktif bir API dökümantasyonu ile karşılaşırsınız:
Ek bilgi
Üstelik, sadece aynı Python tip tanımlaması ile, FastAPI size otomatik ve interaktif (Swagger UI ile entegre) bir dokümantasyon sağlar.
Dikkatinizi çekerim ki, yol parametresi integer olarak tanımlanmıştır.
Standartlara Dayalı Avantajlar, Alternatif Dokümantasyon¶
Oluşturulan şema OpenAPI standardına uygun olduğu için birçok uyumlu araç mevcuttur.
Bu sayede, FastAPI'ın bizzat kendisi http://127.0.0.1:8000/redoc sayfasından erişebileceğiniz alternatif (ReDoc kullanan) bir API dokümantasyonu sağlar:
Aynı şekilde, farklı diller için kod türetme araçları da dahil olmak üzere çok sayıda uyumlu araç bulunur.
Pydantic¶
Tüm veri doğrulamaları Pydantic tarafından arka planda gerçekleştirilir, bu sayede tüm avantajlardan faydalanabilirsiniz. Böylece, emin ellerde olduğunuzu hissedebilirsiniz.
Aynı tip tanımlamalarını str
, float
, bool
ve diğer karmaşık veri tipleri ile kullanma imkanınız vardır.
Bunlardan birkaçı, bu eğitimin ileriki bölümlerinde irdelenmiştir.
Sıralama Önem Arz Eder¶
Yol operasyonları tasarlarken sabit yol barındıran durumlar ile karşılaşabilirsiniz.
Farz edelim ki /users/me
yolu geçerli kullanıcı hakkında bilgi almak için kullanılıyor olsun.
Benzer şekilde /users/{user_id}
gibi tanımlanmış ve belirli bir kullanıcı hakkında veri almak için kullanıcının ID bilgisini kullanan bir yolunuz da mevcut olabilir.
Yol operasyonları sıralı bir şekilde gözden geçirildiğinden dolayı /users/me
yolunun /users/{user_id}
yolundan önce tanımlanmış olmasından emin olmanız gerekmektedir:
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}
Aksi halde, /users/{user_id}
yolu "me"
değerinin user_id
parametresi için gönderildiğini "düşünerek" /users/me
ile de eşleşir.
Benzer şekilde, bir yol operasyonunu yeniden tanımlamanız mümkün değildir:
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"]
Yol, ilk kısım ile eşleştiğinden dolayı her koşulda ilk yol operasyonu kullanılacaktır.
Ön Tanımlı Değerler¶
Eğer yol parametresi alan bir yol operasyonunuz varsa ve alabileceği yol parametresi değerlerinin ön tanımlı olmasını istiyorsanız, standart Python Enum
tipini kullanabilirsiniz.
Bir Enum
Sınıfı Oluşturalım¶
Enum
sınıfını projemize dahil edip str
ile Enum
sınıflarını miras alan bir alt sınıf yaratalım.
str
sınıfı miras alındığından dolayı, API dokümanı, değerlerin string
tipinde olması gerektiğini anlayabilecek ve doğru bir şekilde işlenecektir.
Sonrasında, sınıf içerisinde, mevcut ve geçerli değerler olacak olan sabit değerli özelliklerini oluşturalım:
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"}
Bilgi
3.4 sürümünden beri enumerationlar (ya da enumlar) Python'da mevcuttur.
İpucu
Merak ediyorsanız söyleyeyim, "AlexNet", "ResNet" ve "LeNet" isimleri Makine Öğrenmesi modellerini temsil eder.
Bir Yol Parametresi Tanımlayalım¶
Sonrasında, yarattığımız enum sınıfını (ModelName
) kullanarak tip belirteci aracılığıyla bir yol parametresi oluşturalım:
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"}
Dokümana Göz Atalım¶
Yol parametresi için mevcut değerler ön tanımlı olduğundan dolayı, interaktif döküman onları güzel bir şekilde gösterebilir:
Python Enumerationları ile Çalışmak¶
Yol parametresinin değeri bir enumeration üyesi olacaktır.
Enumeration Üyelerini Karşılaştıralım¶
Parametreyi, yarattığınız enum olan ModelName
içerisindeki enumeration üyesi ile karşılaştırabilirsiniz:
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"}
Enumeration Değerini Edinelim¶
model_name.value
veya genel olarak your_enum_member.value
tanımlarını kullanarak (bu durumda bir str
olan) gerçek değere ulaşabilirsiniz:
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"}
İpucu
"lenet"
değerine ModelName.lenet.value
tanımı ile de ulaşabilirsiniz.
Enumeration Üyelerini Döndürelim¶
JSON gövdesine (örneğin bir dict
) gömülü olsalar bile yol operasyonundaki enum üyelerini döndürebilirsiniz.
Bu üyeler istemciye iletilmeden önce kendilerine karşılık gelen değerlerine (bu durumda string) dönüştürüleceklerdir:
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"}
İstemci tarafında şuna benzer bir JSON yanıtı ile karşılaşırsınız:
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
Yol İçeren Yol Parametreleri¶
Farz edelim ki elinizde /files/{file_path}
isminde bir yol operasyonu var.
Fakat file_path
değerinin home/johndoe/myfile.txt
gibi bir yol barındırmasını istiyorsunuz.
Sonuç olarak, oluşturmak istediğin URL /files/home/johndoe/myfile.txt
gibi bir şey olacaktır.
OpenAPI Desteği¶
Test etmesi ve tanımlaması zor senaryolara sebebiyet vereceğinden dolayı OpenAPI, yol barındıran yol parametrelerini tanımlayacak bir çözüm sunmuyor.
Ancak bunu, Starlette kütüphanesinin dahili araçlarından birini kullanarak FastAPI'da gerçekleştirebilirsiniz.
Parametrenin bir yol içermesi gerektiğini belirten herhangi bir doküman eklemememize rağmen dokümanlar yine de çalışacaktır.
Yol Dönüştürücü¶
Direkt olarak Starlette kütüphanesinden gelen bir opsiyon sayesinde aşağıdaki gibi yol içeren bir yol parametresi bağlantısı tanımlayabilirsiniz:
/files/{file_path:path}
Bu durumda, parametrenin adı file_path
olacaktır ve son kısım olan :path
kısmı, parametrenin herhangi bir yol ile eşleşmesi gerektiğini belirtecektir.
Böylece şunun gibi bir kullanım yapabilirsiniz:
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}
İpucu
Parametrenin başında /home/johndoe/myfile.txt
yolunda olduğu gibi (/
) işareti ile birlikte kullanmanız gerektiği durumlar olabilir.
Bu durumda, URL, files
ile home
arasında iki eğik çizgiye (//
) sahip olup /files//home/johndoe/myfile.txt
gibi gözükecektir.
Özet¶
FastAPI ile kısa, sezgisel ve standart Python tip tanımlamaları kullanarak şunları elde edersiniz:
- Editör desteği: hata denetimi, otomatik tamamlama, vb.
- Veri "dönüştürme"
- Veri doğrulama
- API tanımlamaları ve otomatik dokümantasyon
Ve sadece, bunları bir kez tanımlamanız yeterli.
Diğer frameworkler ile karşılaştırıldığında (ham performans dışında), üstte anlatılan durum muhtemelen FastAPI'ın göze çarpan başlıca avantajıdır.