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ı.
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.
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.
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:
fromfastapiimportFastAPIapp=FastAPI()@app.get("/users/me")asyncdefread_user_me():return{"user_id":"the current user"}@app.get("/users/{user_id}")asyncdefread_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:
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.
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:
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Sonrasında, yarattığımız enum sınıfını (ModelName) kullanarak tip belirteci aracılığıyla bir yol parametresi oluşturalım:
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Parametreyi, yarattığınız enum olan ModelName içerisindeki enumeration üyesi ile karşılaştırabilirsiniz:
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
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:
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_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.
JSON gövdesine (örneğin bir dict) gömülü olsalar bile yol operasyonundakienum üyelerini döndürebilirsiniz.
Bu üyeler istemciye iletilmeden önce kendilerine karşılık gelen değerlerine (bu durumda string) dönüştürüleceklerdir:
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_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: