{"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"}]}
Der Pfad-Parameter item_id hatte den Wert "foo", was kein int ist.
Die gleiche Fehlermeldung würde angezeigt werden, wenn Sie ein float (also eine Kommazahl) statt eines ints übergeben würden, wie etwa in: http://127.0.0.1:8000/items/4.2
Check
Sprich, mit der gleichen Python-Typdeklaration gibt Ihnen FastAPI Datenvalidierung.
Beachten Sie, dass die Fehlermeldung auch direkt die Stelle anzeigt, wo die Validierung nicht erfolgreich war.
Das ist unglaublich hilfreich, wenn Sie Code entwickeln und debuggen, welcher mit ihrer API interagiert.
Wenn Sie die Seite http://127.0.0.1:8000/docs in Ihrem Browser öffnen, sehen Sie eine automatische, interaktive API-Dokumentation:
Check
Wiederum, mit dieser gleichen Python-Typdeklaration gibt Ihnen FastAPI eine automatische, interaktive Dokumentation (verwendet die Swagger-Benutzeroberfläche).
Beachten Sie, dass der Pfad-Parameter dort als Ganzzahl deklariert ist.
Die ganze Datenvalidierung wird hinter den Kulissen von Pydantic durchgeführt, Sie profitieren also von dessen Vorteilen. Und Sie wissen, dass Sie in guten Händen sind.
Sie können für Typ Deklarationen auch str, float, bool und viele andere komplexe Datentypen verwenden.
Mehrere davon werden wir in den nächsten Kapiteln erkunden.
Wenn Sie Pfadoperationen erstellen, haben Sie manchmal einen fixen Pfad.
Etwa /users/me, um Daten über den aktuellen Benutzer zu erhalten.
Und Sie haben auch einen Pfad /users/{user_id}, um Daten über einen spezifischen Benutzer zu erhalten, mittels einer Benutzer-ID.
Weil Pfadoperationen in ihrer Reihenfolge ausgewertet werden, müssen Sie sicherstellen, dass der Pfad /users/me vor /users/{user_id} deklariert wurde:
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}
Ansonsten würde der Pfad für /users/{user_id} auch /users/me auswerten, und annehmen, dass ein Parameter user_id mit dem Wert "me" übergeben wurde.
Sie können eine Pfadoperation auch nicht erneut definieren:
Wenn Sie eine Pfadoperation haben, welche einen Pfad-Parameter hat, aber Sie wollen, dass dessen gültige Werte vordefiniert sind, können Sie ein Standard-Python Enum verwenden.
Importieren Sie Enum und erstellen Sie eine Unterklasse, die von str und Enum erbt.
Indem Sie von str erben, weiß die API Dokumentation, dass die Werte des Enums vom Typ str sein müssen, und wird in der Lage sein, korrekt zu rendern.
Erstellen Sie dann Klassen-Attribute mit festgelegten Werten, welches die erlaubten Werte sein werden:
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"}
Dann erstellen Sie einen Pfad-Parameter, der als Typ die gerade erstellte Enum-Klasse hat (ModelName):
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"}
Sie können ihn mit einem Member Ihres Enums ModelName vergleichen:
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"}
Den tatsächlichen Wert (in diesem Fall ein str) erhalten Sie via model_name.value, oder generell, ihr_enum_member.value:
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"}
Tipp
Sie können den Wert "lenet" außerdem mittels ModelName.lenet.value abrufen.
Sie können Enum-Member in ihrer Pfadoperation zurückgeben, sogar verschachtelt in einem JSON-Body (z. B. als dict).
Diese werden zu ihren entsprechenden Werten konvertiert (in diesem Fall Strings), bevor sie zum Client übertragen werden:
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"}
In Ihrem Client erhalten Sie eine JSON-Response, wie etwa:
OpenAPI bietet nicht die Möglichkeit, dass ein Pfad-Parameter seinerseits einen Pfad enthalten kann, das würde zu Szenarios führen, die schwierig zu testen und zu definieren sind.
Trotzdem können Sie das in FastAPI tun, indem Sie eines der internen Tools von Starlette verwenden.
Die Dokumentation würde weiterhin funktionieren, allerdings wird nicht dokumentiert werden, dass der Parameter ein Pfad sein sollte.
Mittels einer Option direkt von Starlette können Sie einen Pfad-Parameter deklarieren, der einen Pfad enthalten soll, indem Sie eine URL wie folgt definieren:
/files/{file_path:path}
In diesem Fall ist der Name des Parameters file_path. Der letzte Teil, :path, sagt aus, dass der Parameter ein Pfad sein soll.